当前位置: 首页 > news >正文

五、UI自动化测试05--PyTest框架

目录

  • 一、PyTest 框架
    • 2. 特点
    • 2. 安装步骤
    • 3. 基本使⽤
      • 3.1 测试函数形式
      • 3.2 执⾏⽅式
      • 3.3 测试类形式
      • 3.4 执⾏⽅式
      • 3.5 另⼀种执⾏⽅式: 主函数执⾏
      • 3.6 特殊⽅法: 函数级别
      • 3.7 特殊⽅法: 类级别
      • 3.8 特殊⽅法: 函数级别和类级别同时使⽤
    • 4. pytest 配置⽂件
      • 4.1 选项字段获取
      • 4.2 编写步骤
      • 4.3 使⽤步骤
      • 4.4 默认设置
      • 4.5 ⾃定义规则
      • 4.6 扩展: 指定单个⽂件/类/⽅法执⾏
  • 二、 pytest 常⽤插件
    • 1. HTML 报告插件
      • 1.1 安装步骤
      • 1.2 使⽤步骤
    • 2. 控制⽅法执⾏顺序插件
      • 2.1 安装步骤
      • 2.2 使⽤步骤
    • 3. 失败重试插件
      • 3.1 安装步骤
      • 3.2 使⽤步骤
  • 三、pytest ⾼级功能
    • 1. 跳过操作
    • 2. 参数化操作
      • 2.1 单个参数
      • 2.2 多个参数
    • 3. 扩展: 断⾔⽅法的使⽤
      • 3.1 Python ⾃带的断⾔⽅法
      • 3.2 pytest 框架中使⽤断⾔
  • 四、PO 设计模式
    • 1. v0 版本
    • 2. 账户不存在脚本
    • 3. 密码错误脚本

一、PyTest 框架

  • 说明: pytest 是 Python 的⼀种单元测试框架,同⾃带的 UnitTest 测试框架类似,相⽐ UnitTest 框架使⽤起来更简洁,效率更⾼。(在⾃动化测试中同样充当测试执⾏的功能! 并且可以跟 UnitTest 互换)

2. 特点

    1. ⾮常容易上⼿,⼊⻔简单,⽂档丰富,⽂档中有很多实例可以参考
  • 官⽅⽂档地址: https://docs.pytest.org/en/6.2.x/
    1. ⽀持简单的单元测试和复杂的功能测试
    1. ⽀持参数化: UnitTest 需要通过插件扩展参数化功能!
    1. 执⾏测试过程中可以将某些测试跳过,或者对某些预期失败的 Case 标记成失败
    1. ⽀持重复执⾏失败的 Case : 通过安装插件实现
    1. ⽀持运⾏由 Nose,UnitTest 编写的测试 Case : pytest 框架的脚本在 UnitTest 下⽆法执⾏
    1. 具有很多第三⽅插件,并且可以⾃定义扩展
  • 插件获取⽹站:
    • https://docs.pytest.org/en/latest/reference/plugin_list.html
    1. ⽅便的和持续集成⼯具集成

2. 安装步骤

说明: 与 UnitTest 不同的是, pytest 框架需要先安装才能使⽤!

  • 安装:
    • pip install -i https://pypi.tuna.tsinghua.edu.cn/simple pytest
  • 查看: pip show pytest
  • 确认版本: pytest --version

安装与查看版本步骤

在这里插入图片描述

3. 基本使⽤

3.1 测试函数形式

# 函数形式
def test_func(): # 要求函数名以 test 开头"""测试函数"""print('我是测试函数')

3.2 执⾏⽅式

在这里插入图片描述

3.3 测试类形式

# 测试类形式
class TestDemo(object): # 正常定义类, 但是测试类名必须以 Test 开头"""测试示例类"""def test_method1(self): # 正常定义⽅法, 但是测试⽅法名必须以 
test 开头"""测试⽅法1"""print('测试⽅法1')def test_method2(self):"""测试⽅法2"""print('测试⽅法2')

3.4 执⾏⽅式

在这里插入图片描述

3.5 另⼀种执⾏⽅式: 主函数执⾏

说明: 使⽤主函数, 可以实现在代码⽂件内, ⿏标右键菜单执⾏

  • 测试函数形式下使⽤
# 测试函数形式
import pytestdef test_func(): # 要求函数名以 test 开头"""测试函数"""print('我是测试函数')if __name__ == '__main__':# 语法: pytest.main(['-s', '⽂件名.py'])pytest.main(['-s', 'hm03_pytest_basic_03.py'])
  • 测试类形式下使⽤
# 测试类形式
import pytestclass TestDemo(object): # 正常定义类, 但是测试类名必须以 Test 开头"""测试示例类"""def test_method1(self): # 正常定义⽅法, 但是测试⽅法名必须以 test 开头"""测试⽅法1"""print('测试⽅法1')def test_method2(self):"""测试⽅法2"""print('测试⽅法2')if __name__ == '__main__':# 语法: pytest.main(['-s', '⽂件名.py'])pytest.main(['-s', 'hm04_pytest_basic_04.py'])

3.6 特殊⽅法: 函数级别

  • 说明: 函数级别特殊⽅法的执⾏逻辑与 UnitTest 中的 Fixture 的⽅法级别的执⾏逻辑⼀致!
"""
特殊⽅法: 函数级别
"""
import pytestclass TestDemo(object):"""测试示例类"""# 说明: 特殊⽅法名写法固定, 没有代码提示, 需要⼿写!# 注意: 函数级别执⾏顺序: # 先 setup() -> 测试⽅法1 -> teardown() ⽅法, 再 setup() -> 测试⽅法2 -> teardown() ⽅法def setup(self):"""开始⽅法"""print('函数 -> 开始')def teardown(self):"""结束⽅法"""print('函数 -> 结束')def test_method1(self):"""示例测试⽅法"""print('测试⽅法1')def test_method2(self):"""示例测试⽅法"""print('测试⽅法2')if __name__ == '__main__':pytest.main(['-s', 'hm05_pytest_basic_05.py'])

3.7 特殊⽅法: 类级别

  • 说明: 类级别特殊⽅法的执⾏逻辑与 UnitTest 中的 Fixture 的类级别的执⾏逻辑⼀致!
"""
特殊⽅法: 类级别
"""
import pytest
class TestDemo(object):"""测试示例类"""# 说明: 特殊⽅法名写法固定, 没有代码提示, 需要⼿写!# 注意: 类级别执⾏顺序:# 先 setup_class() -> 测试⽅法1 -> 测试⽅法2 -> 
teardown_class() ⽅法def setup_class(self):"""开始⽅法"""print('类 -> 开始')def teardown_class(self):"""结束⽅法"""print('类 -> 结束')def test_method1(self):"""示例测试⽅法"""print('测试⽅法1')def test_method2(self):"""示例测试⽅法"""print('测试⽅法2')if __name__ == '__main__':pytest.main(['-s', 'hm06_pytest_basic_06.py'])

3.8 特殊⽅法: 函数级别和类级别同时使⽤

"""
特殊⽅法: 函数级别和类级别同时使⽤
"""
import pytestclass TestDemo(object):"""示例测试类"""# 执⾏顺序: 1 -> 3 -> 5 -> 4 -> 3-> 6 -> 4 -> 2def setup_class(self): # 1print('类级别 ->> 开始')def teardown_class(self): # 2print('类级别 ->> 结束')def setup(self): # 3print('函数级别 -> 开始')def teardown(self): # 4print('函数级别 -> 结束')def test_method1(self): # 5"""测试⽅法1"""print('测试⽅法1')def test_method2(self): # 6"""测试⽅法2"""print('测试⽅法2')if __name__ == '__main__':pytest.main(['-s', 'hm07_pytest_basic_07.py'])

4. pytest 配置⽂件

  • 说明: 使⽤配置⽂件后可以快速的使⽤配置的项来选择执⾏哪些测试模块
  • 注意:
      1. 在 Windows 系统下, pytest 配置⽂件中, 不允许写注释信息
      1. ⼀个⼯程内只需要⼀个 pytest 配置⽂件, 并且需要保证⽂件名正确
      1. ⼀般情况, 只需要将 pytest 配置⽂件, 置于⼯程根⽬录下
      1. 配置有 pytest 配置⽂件的⼯程, 只需要打开命令⾏, 输⼊ pytest 指令, 即可执⾏测试

4.1 选项字段获取

在这里插入图片描述

4.2 编写步骤

在这里插入图片描述

4.3 使⽤步骤

  • 说明: 打开命令⾏ -> 输⼊ pytest -> 执⾏即可

4.4 默认设置

  • 说明: 测试⽤例⽂件名/测试类名/测试⽅法名均为 Test/test 开头

[pytest]
testpaths = ./case
addopts = -s
python_files = test*.py
python_classes = Test*
python_functions = test*

4.5 ⾃定义规则

  • 说明: 测试⽤例⽂件名/测试类名/测试⽅法名, 需要根据具体项⽬进⾏设置, 以下以 Hm/hm为例

[pytest]
testpaths = ./case
addopts = -s
python_files = hm*.py
python_classes = Hm*
python_functions = hm*

4.6 扩展: 指定单个⽂件/类/⽅法执⾏

[pytest]
testpaths = ./case
addopts = -s
python_files = demo_case1.py
python_classes = DemoDemo1
python_functions = demo_method1

二、 pytest 常⽤插件

1. HTML 报告插件

1.1 安装步骤

  • ⽅式1 -> 安装: pip install pytest-html
  • ⽅式2 -> PyCharm 中安装

在这里插入图片描述

1.2 使⽤步骤

    1. 在 pytest 配置⽂件中, 增加命令选项
    • 选项: --html=./报告路径/报告⽂件名.html --self-contained-html
    • 说明: --self-contained-html 将 CSS ⽂件内嵌到报告⽂件中
    1. 执⾏ pytest 指令, 运⾏测试即可
  • 添加命令选项执⾏
    在这里插入图片描述

  • 查看⽣成的报告内容
    在这里插入图片描述

2. 控制⽅法执⾏顺序插件

2.1 安装步骤

  • ⽅式1 -> 安装: pip install pytest-ordering
  • ⽅式2 -> PyCharm 中安装

在这里插入图片描述

2.2 使⽤步骤

  • 说明: 直接在测试类或测试⽅法上⽅添加 @pytest.mark.run(order=序号)
"""
pytest 控制⽅法执⾏顺序插件
"""
import pytest@pytest.mark.run(order=2)
class TestDemo(object):"""示例测试类"""# 语法: @pytest.mark.run(order=序号)# 注意: run(order=序号) 没有代码提示, 需要⼿写!# @pytest.mark.run(order=-3)def test_method1(self):"""测试⽅法1"""print('测试⽅法1')# @pytest.mark.run(order=1)def test_method2(self):"""测试⽅法2"""print('测试⽅法2')# @pytest.mark.run(order=2)def test_method3(self):"""测试⽅法3"""print('测试⽅法3')# 扩展: 序号⽀持正数和负数, 以及正负混合# 1. 纯正数: 数越⼩, 优先级越⾼[掌握]# 2. 纯负数: 数越⼩, 优先级越⾼[了解]# 3. 正负混合: 正数先按照顺序执⾏, 负数最后执⾏[了解]# 注意: 控制⽅法执⾏顺序对测试类同样有效!
@pytest.mark.run(order=1)
class TestDemo2(object):"""测试类2"""def test_method(self):print('测试类2 -> 测试⽅法')

3. 失败重试插件

3.1 安装步骤

  • ⽅式1 -> 安装: pip install pytest-rerunfailures
  • ⽅式2 -> PyCharm 中安装

在这里插入图片描述

3.2 使⽤步骤

    1. 在 pytest 配置⽂件中, 增加命令选项
    • 选项: --reruns 次数
    1. 执⾏ pytest 指令, 运⾏测试即可
      在这里插入图片描述

三、pytest ⾼级功能

1. 跳过操作

  • 说明: 对于完成的代码或版本不对应的代码, 可以设置跳过使之不参与测试执⾏
"""
跳过功能
"""
import pytestversion = 25 # 模拟软件版本号变量class TestDemo1(object):"""示例测试类"""def test_method1(self):"""测试⽅法"""print('测试⽅法1')# 语法: @pytest.mark.skipif(符合的条件, reason='跳过的原因')# 说明: 如果满⾜条件, 以下⽅法或测试类执⾏跳过, 不执⾏!# 注意: reason= 不能省略, 否则报错!# @pytest.mark.skipif(version >= 25, 'xxx') # 错误样例@pytest.mark.skipif(version >= 25, reason='当前版本不执⾏') # 
正确样例def test_method2(self):"""测试⽅法"""print('测试⽅法2')# 说明: 同样可以跳过测试类
@pytest.mark.skipif(version >= 25, reason='当前版本不执⾏')
class TestDemo2(object):"""示例测试类2"""def test_method(self):print('测试类2 -> 测试⽅法')if __name__ == '__main__':pytest.main(['-s', 'hm10_pytest_skip.py'])

2. 参数化操作

  • 说明: 与 UnitTest 框架不同, pytest 框架⾃带参数化功能, 调⽤对应⽅法并传⼊数据, 即可完成参数化实现

2.1 单个参数

"""
pytest 参数化功能: 单个参数
"""
import pytestclass TestDemo(object):"""示例测试类"""# 语法: @pytest.mark.parametrize('参数变量', ['数值1', '数值
2', ...])@pytest.mark.parametrize('name', ['⼩明', '⼩刚', '⼩红'])def test_method(self, name):"""测试⽅法"""print('获取的名字是:', name)if __name__ == '__main__':pytest.main(['-s', 'hm11_pytest_para1.py'])

2.2 多个参数

"""
pytest 参数化: 多个参数
"""
import pytestclass TestDemo(object):"""示例测试类"""# 语法: @pytest.mark.parametrize('参数1, 参数n', [(数据1-1, 数1-2), (数据2-1, 数据2-2), ...])# 注意:# 1. 多个参数必须置于同⼀个字符串内!# 2. 数据格式必须是: [(), ()] 或者 [[], []]# 扩展: 另⼀种写法# @pytest.mark.parametrize(('name', 'pwd'), [('admin', 
123456), ('test', 654321), ('xxx', 'yyy')])@pytest.mark.parametrize('name, pwd', [('admin', 123456), 
('test', 654321), ('xxx', 'yyy')])def test_method(self, name, pwd):"""测试⽅法"""print('账号:{} 密码:{}'.format(name, pwd))if __name__ == '__main__':pytest.main(['-s', 'hm12_pytest_para2.py'])

3. 扩展: 断⾔⽅法的使⽤

  • 说明: 与 UnitTest 框架不同的是, pytest 框架使⽤ Python ⾃带的断⾔⽅法实现断⾔操作的

3.1 Python ⾃带的断⾔⽅法

# 语法: assert 表达式
# 说明: 断⾔后接的表达式的结果为 Ture(断⾔通过), 为 False(断⾔失败)
# 预期相等:
assert 1 == 1
# 预期包含:
assert 'admin' in '欢迎 admin 归来!'

3.2 pytest 框架中使⽤断⾔

"""
pytest 断⾔
"""
import pytestdef add_func(num1, num2):"""加法函数"""return num1 + num2class TestDemo(object):"""示例测试类"""def test_method(self):"""加法测试⽅法"""# 调⽤被测函数result = add_func(1, 2)# 断⾔判断结果assert 4 == resultif __name__ == '__main__':pytest.main(['-s', 'hm14_pytest_assert.py'])

四、PO 设计模式

1. v0 版本

  • 特点: 对于同⼀个待测模块, 对应的测试代码步骤完全⼀致, 只有测试数据存在差异, 因此对于反复出现的相同逻辑的测试代码, 需要考虑通过封装的思路对⻬进⾏整理, 以提⾼测试脚本的编写效率.
  • 注意: 通过直接定位元素并操作元素的⽅式实现的⾃动化脚本, 已经算是 UI ⾃动化的实现形式了!

2. 账户不存在脚本

"""
账号不存在测试⽤例
"""
from time import sleep
from selenium import webdriverdriver = webdriver.Chrome()
driver.get('http://127.0.0.1/')
driver.maximize_window() # 窗⼝最⼤化
driver.implicitly_wait(10) # 隐式等待# 1. 点击⾸⻚的‘登录’链接,进⼊登录⻚⾯
driver.find_element_by_link_text('登录').click()# 2. 输⼊⼀个不存在的⽤户名
driver.find_element_by_id('username').send_keys('13811110001')
# 3. 输⼊密码
driver.find_element_by_id('password').send_keys('123456')
# 4. 输⼊验证码
driver.find_element_by_id('verify_code').send_keys('8888')
# 5. 点击登录按钮
driver.find_element_by_name('sbtbutton').click()# 6. 获取错误提示信息
# 获取元素⽂本值: 元素对象.text
msg = driver.find_element_by_class_name('layui-layercontent').text
print('错误信息为:',
msg)sleep(3)
driver.quit()

3. 密码错误脚本

"""
密码错误测试⽤例
"""
from time import sleep
from selenium import webdriverdriver = webdriver.Chrome()
driver.get('http://127.0.0.1/')
driver.maximize_window() # 窗⼝最⼤化
driver.implicitly_wait(10) # 隐式等待# 1. 点击⾸⻚的‘登录’链接,进⼊登录⻚⾯
driver.find_element_by_link_text('登录').click()# 2. 输⼊⽤户名
driver.find_element_by_id('username').send_keys('13800001111')
# 3. 输⼊错误密码
driver.find_element_by_id('password').send_keys('error')
# 4. 输⼊验证码
driver.find_element_by_id('verify_code').send_keys('8888')
# 5. 点击登录按钮
driver.find_element_by_name('sbtbutton').click()# 6. 获取错误提示信息
# 获取元素⽂本值: 元素对象.text
msg = driver.find_element_by_class_name('layui-layercontent').text
print('错误信息为:',
msg)sleep(3)
driver.quit()

相关文章:

  • 【SpringBoot】基于MybatisPlus的博客管理系统(1)
  • 【Unity】使用Socket建立客户端和服务端并进行通信的例子
  • 东土科技NewPre系列智能控制器的创新之旅
  • VMware安装 银河麒麟操作系统桌面版 V10 SP1 2403
  • HotSpot的算法细节
  • 集群系统的五大核心挑战与困境解析
  • 4月28号
  • 漏洞复现清单整理-预备梳理,等待补充
  • 多维驱动:负载均衡何以成为现代系统架构的基石
  • 网络爬取需谨慎:警惕迷宫陷阱
  • Ansible安装配置
  • 代发考试战报:4月份 思科认证,华为认证,考试战报分享
  • Twitter 工作原理|架构解析|社交APP逻辑
  • 洛谷题解 | CF1979C Earning on Bets
  • <Revit二次开发> 通过一组模型线构成墙面,并生成墙。Create(Document, IList.Curve., Boolean)
  • 以梦为舟,驶向中医传承新蓝海
  • 宾馆一次性拖鞋很重要,扬州卓韵酒店用品详细介绍其材质与卫生标准
  • Windows 系统下使用 Docker 搭建Redis 集群(6 节点,带密码)
  • (计数)洛谷 P8386 PA2021 Od deski do deski/P10375 AHOI2024 计数 题解
  • Java项目中使用minio存储服务
  • 李铁案二审驳回上诉,维持一审有期徒刑20年的判决
  • 中国人保不再设监事会,国寿集团未再设置监事长职务
  • 这座“蚌埠住了”的城市不仅会接流量,也在努力成为文旅实力派
  • 绿地控股:今年一季度营业收入356亿元,中高层管理人员带头降薪
  • 我国将开展市场准入壁垒清理整治行动
  • 四川落马厅官周海琦受审,1000多人接受警示教育