应用场景:
pytest?框架可以解决我们多个测试脚本一起执行的问题。
它提供了测试用例的详细失败信息,使得开发者可以快速准确地改正问题。它兼容最新版本的 Python。它还兼容?unittest、doctest?和?nose,开箱即用。接下来我们详细了解下pytest框架。
01
安装和介绍
概念:
pytest?是?python?的一种单元测试框架,同自带的 Unittest?测试框架类似,相比于 Unittest?框架使用起来更简洁,效率更高
官网:https://docs.pytest.org/en/latest/
中文文档地址:https://www.osgeo.cn/pytest/
01
特点和书写规则
特点:
非常容易上手,入门简单,文档丰富,文档中有很多实例可以参考
支持简单的单元测试和复杂的功能测试
支持参数化
执行测试过程中可以将某些测试跳过,或者对某些预期失败的 Case?标记成失败?支持重复执行失败的 Case
支持运行由 Nose, Unittest 编写的测试 Case
具有很多第三方插件,并且可以自定义扩展
方便的和持续集成工具集成
安装:
通过pip命令安装指定版本
pip3 install?pytest==5.4.3
pytest是python的第三方测试框架,是基于unittest的扩展框架,比unittest更简洁,更高效。
使用 pytest编写用例,必须遵守以下规则:
测试文件名必须以“test”开头或者"test"结尾(如:test_ab.py)
测试方法必须以“test”开头。test*.py或?*test.py
测试类命名以“Test”开头。用例识别:包含所有test_*的方法(测试类不能带有— init—方法) ?
断言使用基本的assert即可
使用pytest?需要更改pycharm?集成设置
Pytest?可以执行uinttest 写的用例和方法
02
运行方式
运行方式分为两种
命令行模式【建议】
主函数模式
命令行模式【建议】
命令行中执行 pytest?-stest_demo01.py
主函数模式
import?pytest
class?Test:
def?test_case01(self):
print(1)
def?test_case02(self):
print(2)
#?主函数执行
if?__name__ == '__main__':
pytest.main(['-s','test_demo01.py'])
在test_demo01.py文件中增加主函数
-s?表示支持控制台打印,如果不加,print 不会出现任何内容
运行结果
.?表示成功 ???
F?表示失败
小结:建议使用命令行的形式运行,对比主函数模式更加方便
03
setup?和?teardown
pytest?在运行自动化脚本的前后会执行两个特殊的方法,分别是?setup?和?teardown?在执行脚本之前会执行 setup方法,在执行脚本之后会执行 teardown?方法,我们可以在 setup?中进行获取驱动对象的操作,在teardown?中进行关闭驱动对象的操作
应用场景:
函数级别方法
运行于测试方法的始末,运行一次测试函数会运行一次 setup?和teardown。
示例代码
import?pytest
class?Test:
def?setup(self):
print('test--->setup')
def?teardown(self):
print('test--->teardown')
def?test_case01(self):
print('test--->1')
def?test_case02(self):
print('test--->2')
#?主函数执行
if?__name__ == '__main__':
pytest.main(['-s','test_demo01.py'])
执行结果
示例代码
import?pytest
class?Test:
def?setup_class(cls):
print('test--->setupcls')
def?teardown_class(cls):
print('test--->teardowncls')
def?test_case01(self):
print('test--->1')
def?test_case02(self):
print('test--->2')
#?主函数执行
if?__name__ == '__main__':
pytest.main(['-s','test_demo01.py'])
执行结果
02
Pytest-常用插件
插件列表网址:??https://plugincompat.herokuapp.com包含很多插件包,大家可依据工作的需求选择?使用。
01
Pytest-html测试报告
应用场景
自动化测试脚本最终执行是通过还是不通过,需要通过测试报告进行体现
使用命令进行安装 指定版本
pip?install?pytest-html=2.1.1
执行命令
pytest?test_login.py?--html=report.html
查看报告
报告展示:
02
控制函数执行顺序
应用场景:
现实生活中,如果想下订单,必须先登录,我们可以通过插件的形式来控制函数执行的顺序?安装
使用命令 pip3 install?pytest-ordering
标记于被测试函数,@pytest.mark.run(order=x)
根据order传入的参数来解决运行顺序
order值全为正数或全为负数时,运行顺序:值越小,优先级越高
正数和负数同时存在:正数优先级高
示例代码
import?pytest
class?Test:
def?test_case01(self):
print('test--->001')
@pytest.mark.run(order=2)
def?test_case02(self):
print('test--->002')
@pytest.mark.run(order=1)
def?test_case03(self):
print('test--->003')
执行结果
03
失败重试
应用场景:
由于网络的原因造成自动化脚本报错,我们可以使用失败重试的插件,当失败后尝试再次运行,一般情况最终成功可以视为成功,但最好进行进行排查时候是脚本问题
使用命令pip3install?pytest-rerunfailures?进行安装使用
在配置文件中的命令行参数中增加 -- reruns?n
pytest??-s?test_demo2.py?--reruns?3
示例代码
class?Test:
def?test_a(self):
assert?1,1 # 断言成功
def?test_b(self):
print('失败')
assert?0,1 # 断言失败
运行结果
R?表示重试
注意重试时,如果脚本通过,那么后续不再重试
03
pytest高级用法
01
跳过测试函数
应用场景:
同一个软件在不同的设备上可能会有不同的效果,比如,iOS?的 3d?touch?操作是需要 6s?以上设备支持?的,6 和 6s?都可以安装同一款应用,如果设备不支持,那么根本没有必要去测试这个功能。此时,我们可以让这种函数进行跳过
使用方式:
在需要跳过的测试脚本之上加上装饰器 @pytest.mark.skipif(condition, reason="xxx")
condition
reason
跳过的条件,必传参数
标注原因,必传参数
示例代码:
class?Test:
def?test_a(self):
assert?1,1 # 断言成功
@pytest.mark.skipif(condition=True,reason='x')
def?test_b(self):
print('失败')
assert?0,1 # 断言失败
执行结果
02
预期失败
应用场景:
举例,测试手机号码输入框长度为11位数字,如果我们传入一个 12 位数字,此时可以使用预期失败
@pytest.mark.xfail(condition=None, reason=None, raises=None, run=True,?strict=False)
condition??跳过条件,必填参数
reason???????标注原因,必填参数
使用方式:
在需要标记预期失败的测试脚本之上加上装饰器示例
示例代码:
class?Test:
def?test_a(self):
print('-----testa')
assert?1,1 # 断言成功
@pytest.mark.xfail(condition=True,reason='x')
def?test_b(self):
print('-----testb')
assert?0,1 # 断言失败
@pytest.mark.xfail(condition=True, reason='x')
def?test_c(self):
print('-----testc')
assert?0,?2 ?# 断言失败
执行结果:
x?表示预期失败结果失败 不算是bug,X?表示预期失败结果成功 算是bug
03
数据参数化
应用场景:
登录功能都是输入用户名,输入密码,点击登录。但登录的用户名和密码如果想测试多个值是没有办法?用普通的操作 ?实现的。数据参数化可以帮我实现这样的效果。
方法名:
@pytest.mark.parametrize(argnames, argvalues, indirect=False, ids=None,?scope=None)
argnames??参数名
argvalues???参数对应值,类型必须为可迭代类型,一般使用list
一个参数使用方式
argnames?为字符串类型,根据需求决定何时的参数名
argvalues?为列表类型,根据需求决定列表元素中的内容
在测试脚本中,参数,名字与 argnames?保持一致
在测试脚本中正常使用
argvalues?列表有多少个内容,这个脚本就会运行几次
示例代码:
class?Test:
@pytest.mark.parametrize('age',[18,19,23,21])
def?test_01(self,age):
print(age)
执行结果:
多个参数:
class?Test:
@pytest.mark.parametrize(('name','age'),[('zhangsan',18),('lisi',19)])?
def?test_01(self,name,age):
print(name,age)
执行结果:
04
Pytest-?xture
应用场景:
?xture??修饰器来标记固定的工厂函数,在其他函数,类调用它时会被激活并优先执行,通常会被用于完成预置处理和重复操作
使用方式:
通过函数引用
示例代码:
class?Testlogin:
@pytest.fixture()
def?test_login(self):
print('登录操作')
uname?= 'lily'
return?uname
def?test_a(self,test_login):
print(f'test_a?{test_login}')
def?test_b(self):
print('不需要登录操作')
?运行结果: