该框架可以专注与写测试用例,将繁琐的编码工作统统干掉,使用插件式,可自定义插件,例如破解验证码,失败截图等 测试用例写完后只需指定使用的插件和测试用例,便可自动测试,生成报告,发送邮件
用例:
- Reader: 读取数据的工具,可以指定文件或者数据库或者自定义
- Case: 一个元素的定位方式执行动作等(一个执行步骤)
- Process: 一系列执行步骤(根据id排序)
- Package: 运输的基本单元 用于将一个Process或者多个Process打包
- Packages: 所有Package的集合
- Packager: 负责将Case和Process结合并打包成Package形成Packages
- Porter: 负责从Packager取到数据送给CaseManager
- CaseManager: 负责从管理多个Porter和Packager
执行:
- ExecuteCenter: 负责从CaseManager的搬运工手中获取Packages,并分发给Manager
- Manager: 将packages中的每一个package分配给已注册的Executor
- Executor: 负责将package解包获取Process并执行
- PluginCenter: 插件中心,负责插件的注册管理等
- Plugin:插件,将功能实现后注册到PluginCenter中,测试时将调用功能
其他:
- Generator:用于生成Test脚本
- Report:执行用例生成报告
由Reader读取测试用例(db,file) -> 形成每个执行步骤(Case) -> 多个执行步骤形成流程(Process)
Packager将Process打包(Package) -> 多个Package形成包集合(Packages,可扩展成异步操作,分布式操作)
由Porter(搬运工)将Packages运送到CaseManager中 -> 由Manager进行调度给命令执行中心(ExecutorCenter)
ExecutorCenter进行解包分发给执行器 -> 各执行器执行分配给自己的任务
- selenium
- xlrd
PageObject会根据测试用例自动生成xxx.ini文件,每次执行时都会清理
1.所有section都是一个测试流程所需的元素
2.所有元素命名方式:
元素名.method 表示该元素的定位方式
元素名.value 表示该元素的定位的值
3.定位方式的写法
"id":id定位
"xpath":xpath定位
"link_text" link的文字
"partial_link_text":包含link的文字
"name":元素name
"tag_name":元素标签名
"class_name": 类名
"css_selector": css选择器
4.元素名命名方式
命名:元素名_控件名
元素的含义例如用户名,密码等含义使用驼峰命名
例如
输入框:
元素名_input:
用户名输入框-> user_input
密码输入框 -> pwd_input
关键词搜索输入框 -> kw_search_input
复选框:
元素名_checkbox:
自动登录复选框 -> autoLogin_checkbox
5.元素的行为 每个元素都会赋予一定的行为
按钮行为可以是点击,可以是拖动
输入框可以是点击,可以是输入
完整命名方式:
元素名_控件名.action = 行为
例如:
密码输入框
registerPassword_input.method=id
registerPassword_input.value=user_password
registerPassword_input.action=send_keys
registerPassword_input.input_value=123456
配置文件放在managers/config.py
# 当前文件路径 current_path = os.path.dirname(__file__) # 元素名称转换映射关系 element_name = { "输入框": "_input", "按钮": "_button", "下拉列表": "_select", "iframe": "_iframe", "js": "_java_script", "链接": "_link", } url = { # 生成缓存路径 "page_object_file_path": current_path, "delete": True } selenium = { # selenium使用的浏览器 "browser": "firefox", # 当前平台,如果没有指定默认使用当前系统 "os": "linux", # 浏览器驱动地址 "driver_path": "/home/amdins/桌面/geckodriver", "log_path": current_path, "log_name": "geckodriver.log", "delete_log": True } report = { # 生成的测试脚本路径(是文件夹!) "file_url": "/home/amdins/桌面/text", # 测试报告路径 "report_file_path": "home/amdins/桌面/text/report.html" } email = { "use_email": False, # 邮件使用的服务器 "stmp_server_addr": "smtp.yeah.net", # 邮件中发送者邮箱 "author": "VenmoSnake@example.com", # 邮件中接受者邮箱 "recv_email": "Report@exmaple.com", # 邮箱服务器用户名 "username": "Administrator", # 邮箱服务器密码 "password": "AdministratorPwd", # 使用的邮箱模板,default表示使用默认的,如果使用自定义模板需要指定模板路径 "template": "default", # 邮箱发送的信息 "message": "Test Case", # 邮箱的Subject "title": "Test" } case = { # 选择测试用例的类型 excel表示用excel文件中读取,db表示从数据库读取 "type": "excel", # 文件路径或者db的uri "url": "/home/amdins/桌面/SeleniumAutoTest/case.xlsx", # 生成的case信息文件路径 "case_info": current_path, # 是否序列化Packages "serialize_packages": True, # 是否删除序列化文件 "delete_serialize_packages": True, # 序列化路径 "serialize_path": current_path, # 用例起始url "base_url": "https://music.163.com/" } # 注册的插件 plugins = [ "assertion" ]
测试用例暂时只支持excel,不过可以自己增加读取方式
用例说明:
| 编号 | 描述 | 生成的元素名称 | 元素类别 | 定位方式 | 定位值 | 动作 | 输入值 | 等待方式 | 等待时间 | 执行动作 | 使用插件 | 断言条件 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 5 | 播放歌曲 | playSong | 按钮 | xpath | //a[@title='播放'] | 点击 | 不等待 | 0 | assertion:A | is(element_text|`xpath`,`//em[contains(text(),'我爱的人走了')]`|::'我爱的人走了') |
填写插件名,以逗号分割,需要指定什么时候执行B表示在执行测试用例之前执行,A表示在执行测试用例之后执行,E表示在发生异常时执行插件
不是使用插件可以置空或者为null
断言使用断言插件完成,断言方式可自定义
执行动作表示浏览器要执行的动作,滚动条操作,窗口切换等
可以指定动作在什么时候执行
例如:
在执行测试用例之前执行:win_max:B
在执行测试用例之后执行:win_min:A
浏览器执行动作优先级比插件的高
|动作名|含义| |win_max|最大化窗口| |win_min|最小化窗口| |win_full|窗口全屏| |switch_last|切换到最后一个窗口| |switch_first|切换到第一个窗口| |switch_index(index)|切换到第index个窗口| |alter_accept|点击确定| |alter_dismiss|点击取消| |alter_send(str)|在alter中发送str| |page_forward|网友前进| |page_back|网页后退|
from case.reader.excel import ExcelReader from execute.driverexecute import NormalExecutor from plugin.assertplugin import AssertPlugin from report.Runner import Run from report.report import Report if __name__ == '__main__': r = Run() r.add_executor(NormalExecutor()) r.add_plugin(AssertPlugin("assertion")) r.add_reader(ExcelReader()) r.generator_file("case") report = Report() report.start()
注意: 断言插件默认已经被注册,名称为assertion
可以指定插件在什么时刻执行
例如: 在测试用例之前执行:assertion:B (before) 在测试用例之后执行:assertion:A (After)
from plugin.base import BasePlugin from exception.assertion import Assertion class ScreenPlugin(BasePlugin): def start(self, driver,case): """ driver为webdriver对象 case为当前执行的case """ if case.assertion not in driver.page_source: raise Assertion()
断言插件在断言失败时会抛出AssertionError()
实现原理: 根据测试用例生成xx_test.py文件,然后使用unittest的testLoader,结合TestRunner实现
conver = unittest.defaultTestLoader.discover("路径", pattern="*_test.py") with open("result.html", 'wb') as f: HTMLTestRunner(title="测试标题", description="测试描述", tester="测试员", stream=f).run(cover)
from case.reader.excel import ExcelReader from execute.driverexecute import NormalExecutor from plugin.assertplugin import AssertPlugin from report.Runner import Run # 生成器 r = Run() # 注册执行器 r.add_executor(NormalExecutor()) # 注册插件 r.add_plugin(AssertPlugin("assertion")) # 注册Reader r.add_reader(ExcelReader()) # 生成文件 r.generator_file("case")
import unittest from managers.manager import Manager from case.reader.excel import ExcelReader from execute.driverexecute import NormalExecutor from plugin.assertplugin import AssertPlugin man = Manager() man.select_reader(ExcelReader()) man.register_executor(NormalExecutor()) man.register_plugin(AssertPlugin('assertion')) execute = man.get_execute() class case(unittest.TestCase): def test_Test(self): execute.run_by_name('Test')
- 框架骨架
- 插件支持
- 丰富元素动作
- 断言插件
- 测试报告生成(待完善)
- 邮件支持
- 丰富浏览器行为
- 丰富插件
- 异步执行
- 从数据库读取测试用例
- 远程测试支持
- 作为Docker服务