UI自动化详细教程
一、安装部署
1.执行环境(建议下载python3.9)
①python官网地址
②下载完成后无脑下一步(注:勾选Add Python 3.9 to PATH,否则需配置环境变量)
③查看是否安装成功
win+r 输入cmd
2.解压代码
①得到的代码解压至自定义目录,解压后如图所示
②配置allure环境变量
复制allure插件的bin路径至环境变量path中
3.配置代码
①配置代码执行环境(以pychram为例)
右下角选择Interpreter Settings...
设置弹窗右上角选择Add...
Base interpreter 选择环境安装地址
②安装依赖(依赖管理放在requirements.txt下)
终端输入:pip install -r requirements.txt
③下载chromDriver驱动
将chrom浏览器对应版本的chromDriver驱动下载解压移动至此文件夹下
④修改配置文件内容
替换自己的用户名、密码和图片路径地址
⑤执行
执行代码查看是否成功
选择run文件点击执行或右击run文件点击执行
⑥查看报告
因.gitignore文件配置report文件夹不提交导致文件夹隐藏,需在左上角选择report文件夹(建议使用Edge浏览器打开,其他浏览器打开会出现404问题)
二、代码结构
框架基于selenium+pytest+allure实现,页面元素为elementUI组件,按区域来封装组件元素以及组件行为(如一个输入框为一个组件,参考elementUI中文官网)
elementUI中文官网:https://element.eleme.cn/#/zh-CN/component/installation
1.testcase:存放测试用例文件,按模块分为初始化用例和单元测试用例,如一个菜单为一个模块
2.action:存放执行步骤文件,按区域将相同的组件行为和操作行为进行封装
3.pages:存放页面元素文件,按区域将相同的页面元素进行封装
4.js:存放测试数据文件,可以反复使用
5.resoure:存放配置文件以及chromDriver驱动
6.utils:存放公共工具类文件
7.pytest.ini:pytest配置文件
8..gitignore:忽略某个文件夹或者文件提交到git的文件
9.requirements.txt:存放依赖名称以及指定依赖版本,便于与他人协同开发。安装依赖命令为:pip install -r requirements.txt
10.allure-2.13.9:allure插件,该插件能生成allure报告。可放置其他位置,需在环境变量path中新增该插件的bin路径(或直接指定该bin路径)使用allure命令
11.browsermob-proxy-2.1.4:浏览器代理插件,该插件能在浏览器调用接口时获取所有接口的参数和响应数据。可放置其他位置,需在代码中指定该插件的.bat文件(本文中用来获取验证码)
12.report、temp:allure插件生成的报告和报告缓存文件,使用allure命令或者在pychram中右击report/index.html文件可查看报告,或report目录下cmd执行:allure serve report 和 allure open report
13.run:整个代码执行的主入口
三、代码解析
以商品分类模块新增为例
1.run文件为主入口,执行用例并当执行完成后生成报告文件
若指定py文件路径,可只执行改文件用例
2.执行run文件pytest就会执行1_classification_test用例文件
pytest会根据pytest.ini里的配置找到以test.py结尾的文件,执行该文件下以Test结尾的类和test结尾的方法
1_classification_test.py文件前面序号1为了让pytest能按顺序去执行测试用例文件
3.conftest.py的login方法
执行前*test.py文件前会先执行conftest.py文件的login方法,此方法前后置方法。因为autouser=False,所以需在测试类上加上@pytest.mark.usefixtures("driver")才能调用该fixture
大致内容如下:
·记录用例执行开始时间,并写在allure步骤中
·设置浏览器代理,为了获取验证码
·启动driver控制浏览器并进入登录页
·登录
·记录用例执行结束时间,并写在allure步骤中
·执行完成后关闭驱动代理
·如果期间发生异常则会自动进行浏览器截图,并添加到allure报告中
4.ClassificationTest的setup_function方法
setup_function也为该类的前置方法autouse=True表示会自动调用。会先执行conftest里的login()方法,再执行此方法
·driver参数:调用fixture就会获取该参数
·self.page = ClassificationPage(self.driver):实例化商品分类页面元素类
·self.action = ClassificationAction(self.driver):实例化商品分类操作行为类
·self.action.into():进入菜单页面,调用ClassificationAction下的into方法
ClassificationAction里的into方法是进入该模块菜单页面,该模块用例执行前都必须先进入页面,故此将此步骤封装至模块文件中,只需调用即可进入该页面
self.meun_into(page.menu_baseInfo(), page.menu_classification()):调用meunAction的meun_into方法,传参为一级菜单名称和二级菜单名称
MeunAction里的menu_into方法是进入该模块菜单页面,因为该所有模块用例执行前都必须先进入页面,故此将此步骤封装。与into不同的是这里需要参数一级菜单名称和二级菜单名称
大致内容如下:
·参数:first(一级菜单名称)second(二级菜单名称)
·allure.step():每次调用此方法会在报告中记录该步骤
·获取一级菜单的class,如果菜单已展开class会有“is-opened”,根据此判断菜单是否展开。若展开则无需点击(点击会导致菜单收缩)
·点击二级菜单
MeunPage里的menu方法是获取菜单按钮元素,如下图会发现菜单只会在//ul[@role=’menubar’]这个区域中,因此利用xpath的相对定位先找到区域,然后在这个区域中通过菜单名称可定位到具体菜单按钮。故将此元素按照菜单区域封装,只需传入菜单名称即可找到该元素(具体定位学习参考xpath文档)
getElement是使用lambda表达式获取具体元素对象。隐式等待,即会在20秒内在页面中寻找元素,若超时则抛异常不会一直等。然后执行下一用例
5.ClassificationTest的add_test方法(商品分类新增用例方法)
add_test新增流程用例
@allure.title("新增流程"):allure用例标题
@allure.severity("blocker"):allure用例等级
@pytest.mark.parametrize('data', addJs):参数化,数组有多个字典,有多少个字典执行多个次
self.action.add(data):新增操作
self.action.alert_get():获取提示
AsserUtil.assert_success(hint):提示信息是否和预期一致
ClassificationJs的addJs为测试数据
classification_name: RandomUtil().random_unicode(5):随机5位数中文字符
status: “启用”:状态为启用
6.ClassificationAction的add方法
按模块将所有此模块操作步骤封装到此类中,大至内容如下:
·打开新增对话框
·填写对话框内容
·点击确定按钮
FunctionAction的function_button_click方法
按区域将所有功能区操作步骤封装到此类中
·传参:”新增”字符串
·通过”新增”字符串,在功能区-按钮元素中找到新增按钮
·点击功能区-”新增”按钮
FunctionPage的function_button方法
按区域将所有功能区元素封装到此类中
·xpath解析:先通过相对定位//div[@class=’function-area’]找到此区域,然后在此区域下通过按钮文本找到该元素
·传参:按钮文本
·通过按钮文本,在功能区-按钮元素中找到该按钮
ClassificationAction的dialog_fill方法
按模块将所有此模块操作步骤封装到此类中
·传参:测试数据
·self.dialog_sendKeys(page.classification_name(), data):分类名称对话框输入数据
·self.dialog_radioButton_click(page.dialog_status(), data):状态单选按钮选择数据
DialogAction的dialog_sendKeys方法
按区域将所有对话框区操作封装到此类中
·传参:web(页面信息字典),data(测试数据)
·label = web["label"]:页面文本
·field = web["field"]:测试数据key
·data = data[field]:通过key找到测试数据对应的值
·page.dialog_input(label):通过(label)名称获取对话框输入框元素
·self.send_keys(element, data):对话框-输入框输入测试数据
·page.dialog_input(label):通过(label)名称获取对话框输入框标签元素
·self.click(element1):点击标签元素,因为部分用例需让输入框失去焦点
DialogAction的dialog_input方法
按区域将所有对话框区元素封装到此类中
·传参:label(输入框标签名)
·xpath解析:先通过相对定位//div[@class='el-dialog__wrapper' and not(contains(@style,'display: none'))]找到打开的对话框,因为新增和编辑有两个对话框
关闭的对话框样式为display:none;,然后在对话框下通过输入框标签找到输入框。 textarea为文本框,用 | 可将这两种输入框都定位到
7.AlertAction的alert_get方法
按区域将所有警告操作封装到此类中
·page.alert():获取警告元素
·self.get_attribute(element,"textContent").strip():获取警告元素内文本信息
AlertPage的alert方法
按区域将所有警告区元素封装到此类中
·xpath解析:先通过相对定位//div[@role=’alret’]找到警告区域,然后在区域内获取文本元素
·返回:元素对象
PublicAction的get_attribute方法
所有公共操作封装到此类中,如点击、输入、获取文本等
·传参:element(元素对象),type(属性类型)
·element.get_attribute(type):获取元素属性
·返回:元素属性信息
8.AssertUtil的assert_success方法
按所有断言封装到此类中
传参:expect(预期值),webData(页面值)
将预期值和页面值转成字符串然后进行断言
assume插件:一个用例可能有多个断言,此插件可以使断言失败不终止
四、测试报告
会记录结果、用例名称、等级、测试数据、测试步骤,测试起始时间等
1.成功报告
2.失败报告
如果测试失败会有失败截图,以及失败原因