Pytest自动化测试全面解析
目录
一、前言pytest是一个非常成熟的全功能的Python测试框架,主要特点:
二、pytest安装
2.1、安装 pip install -U pytest
2.2、验证安装 pytest –version # 会展示当前已安装版本
2.3、pytest文档 官方文档:https://docs.pytest.org/en/latest/contents.html
三、pytest框架的约束
3.1、 python的命名规则
3.2、 pytest的命名规则
四、pytest的运行方式
4.1、主函数运行编辑main中可使用的参数有:
4.2、命令行运行
4.3、pytest.ini配置文件方式运行(常用)
mian执行方式还是命令执行,都会去读取pytest.ini文件编辑
五、pytest配置文件pytest.ini文件
六、pytest的常用插件
七、pytest中conftest.py文件
7.1、conftest.py的特点
7.2、conftest.py的示例目录,最顶层的 conftest,一般写全局的 fixture
八、pytest中fixtrue装饰器
8.1、前言
8.2、fixtrue的优势
8.3、Fixture的调用方式:@pytest.fixture(scope = "function",params=None,autouse=False,ids=None,name=None)
8.4、Fixture的作用范围
8.5、fixtrue参数详解-scope
8.5.1、scope = “function”
8.5.2、scope = “class”测试类内的每一个测试方法都调用了fixture,fixture只在该class下所有测试用例执行前执行一次
8.5.3、scope = “module”:与class相同,只从.py文件开始引用fixture的位置生效
编辑
8.5.4、scope = “session”:
8.6、fixtrue参数详解-autouse
默认False,若为True,刚每个测试函数都会自动调用该fixture,无需传入fixture函数名由此我们可以总结出调用fixture的三种方式: 1.函数或类里面方法直接传fixture的函数参数名称 2.使用装饰器@pytest.mark.usefixtures()修饰 3.autouse=True自动调用,无需传仍何参数,作用范围跟着scope走(谨慎使用)让我们来看一下,当autouse=ture的效果:编辑
8.7、fixtrue参数详解params
8.8、fixtrue参数详解-ids
8.9、fixtrue参数详解-name
九、pytest跳过测试用例skip、skipif
9.1、@pytest.mark.skip跳过执行测试用例,有可选参数 reason:跳过的原因,会在执行结果中打印
9.2、pytest.skip()函数基础使用作用:在测试用例执行期间强制跳过不再执行剩余内容类似:在Python的循环里面,满足某些条件则break 跳出循环编辑
9.3、 pytest.skip(msg=“”,allow_module_level=False)
9.4、 pytest.skip(msg=“”,allow_module_level=False)
9.5、跳过标记
9.6、pytest.importorskip( modname: str, minversion: Optional[str] = None, reason: Optional[str] = Nonse )作用:如果缺少某些导入,则跳过模块中的所有测试参数列表
9.7、使用自定义标记 mark
十、Pytest参数化 @pytest.mark.parametrize
10.1、函数数据参数化
十一、pytest标记为失败函数和失败重试
十二、pytest生成测试报告
1、下载Allure插件
2、生成临时的json报告(过度)
3、生成html报告
4、allure测试报告优化
十三、pytest中管理日志
1、日志级别
2、分析解释
3、日志输出-控制台
4、日志输出-文件
5、日志输出-控制台和文件
6、format常用格式说明
7、捕捉异常traceback记录编辑
8、日志滚动和过期删除(按时间)编辑
十四、总结
一、前言
pytest是一个非常成熟的全功能的Python测试框架,主要特点:
1、简单灵活,非常方便的组织自动化测试用例;
2、支持参数化,可以细粒度地控制要测试的测试用例;
3、能够支持简单的单元测试和复杂的功能测试,比如web端selenium/移动端appnium等自动化测试、request接口自动化测试
4、pytest具有很多第三方插件,并且可以自定义扩展,比如测试报告生成,失败重运行机制
5、测试用例的skip和fail处理;
6、结合业界最美的测试报告allure+Jenkins,持续集成
二、pytest安装
2.1、安装 pip install -U pytest
2.2、验证安装 pytest –version # 会展示当前已安装版本
2.3、pytest文档 官方文档:https://docs.pytest.org/en/latest/contents.html
三、pytest框架的约束
3.1、 python的命名规则
1)py文件全部小写,多个英文用_隔开
2)class名首字母大写,驼峰
3)函数和方法名小写,多个英文用_隔开
4)全局变量,前面要加global
5)常量字母必须全大写,如:AGE_OF_NICK
3.2、 pytest的命名规则
1)模块名(py文件)必须是以test_开头或者_test结尾
2)测试类(class)必须以Test开头,并且不能带init方法,类里的方法必须以test_开头
3)测试用例(函数)必须以test_开头
四、pytest的运行方式
4.1、主函数运行

main中可使用的参数有:
参数 | 描述 | 案例 |
---|---|---|
-v | 输出调试信息。如:打印信息 | pytest.main([‘-v’,‘testcase/test_one.py’,‘testcase/test_two.py’]) |
-s | 输出更详细的信息,如:文件名、用例名 | pytest.main([‘-vs’,‘testcase/test_one.py’,‘testcase/test_two.py’]) |
-n | 多线程或分布式运行测试用例 | |
-x | 只要有一个用例执行失败,就停止执行测试 | pytest.main([‘-vsx’,‘testcase/test_one.py’]) |
– maxfail | 出现N个测试用例失败,就停止测试 | pytest.main([‘-vs’,‘-x=2’,‘testcase/test_one.py’] |
–html=report.html | 生成测试报告 | pytest.main([‘-vs’,‘–html=./report.html’,‘testcase/test_one.py’]) |
-m | 通过标记表达式执行 | |
-k | 根据测试用例的部分字符串指定测试用例,可以使用and,or |
4.2、命令行运行
4.3、pytest.ini配置文件方式运行(常用)
mian执行方式还是命令执行,都会去读取pytest.ini文件

pytset.ini文件尽可能不要出现中文。
五、pytest配置文件pytest.ini文件
pytest的配置文件通常放在测试目录下,名称为pytest.ini,命令行运行时会使用该配置文件中的配置
六、pytest的常用插件
插件列表网址:https://plugincompat.herokuapp.com
包含很多插件包,大家可依据工作的需求选择使用。
七、pytest中conftest.py文件
7.1、conftest.py的特点
7.2、conftest.py的示例目录,最顶层的 conftest,一般写全局的 fixture
八、pytest中fixtrue装饰器
8.1、前言
虽然setup和teardown可以执行一些前置和后置操作,但是这种是针对整个脚本全局生效的
如果有以下场景:
-
用例一需要执行登录操作;
-
用例二不需要执行登录操作;
-
用例三需要执行登录操作,则setup和teardown则不满足要求。
-
fixture可以让我自定义测试用例的前置条件
8.2、fixtrue的优势
8.3、Fixture的调用方式:
@pytest.fixture(scope = "function",params=None,autouse=False,ids=None,name=None)
8.4、Fixture的作用范围
8.5、fixtrue参数详解-scope
8.5.1、scope = “function”

从运行结果可以看出,fixture做为参数传入时,会在执行函数之前执行该fixture函数。再将值传入测试函数做为参数使用,这个场景多用于登录


- 即使fixture之间支持相互调用,但普通函数直接使用fixture是不支持的,一定是在测试函数内调用才会逐级调用生效
- 有多层fixture调用时,最先执行的是最后一层fixture,而不是先执行传入测试函数的fixture
- 上层fixture的值不会自动return,这里就类似函数相互调用一样的逻辑
8.5.2、scope = “class”
测试类内的每一个测试方法都调用了fixture,fixture只在该class下所有测试用例执行前执行一次
测试类中的测试方法使用了fixture函数名,fixture只在该class下第一个使用fixture函数的测试用例位置开始算,后面所有的测试用例执行前只执行一次。而该位置之前的测试用例就不管。
语法
1@pytest.fixture(scope='class')
8.5.3、scope = “module”:与class相同,只从.py文件开始引用fixture的位置生效
8.5.4、scope = “session”:
8.6、fixtrue参数详解-autouse
默认False,若为True,刚每个测试函数都会自动调用该fixture,无需传入fixture函数名
由此我们可以总结出调用fixture的三种方式:
1.函数或类里面方法直接传fixture的函数参数名称
2.使用装饰器@pytest.mark.usefixtures()修饰
3.autouse=True自动调用,无需传仍何参数,作用范围跟着scope走(谨慎使用)
让我们来看一下,当autouse=ture的效果:
8.7、fixtrue参数详解params
Fixture的可选形参列表,支持列表传入
默认None,每个param的值
fixture都会去调用执行一次,类似for循环
可与参数ids一起使用,作为每个参数的标识,详见ids
被Fixture装饰的函数要调用是采用:Request.param(固定写法,如下图)
8.8、fixtrue参数详解-ids
用例标识ID与params配合使用,一对一关系,配置了IDS后:
8.9、fixtrue参数详解-name
fixture的重命名
通常来说使用 fixture 的测试函数会将 fixture 的函数名作为参数传递,但是 pytest 也允许将fixture重命名
如果使用了name,那只能将name传如,函数名不再生效
调用方法:@pytest.mark.usefixtures(‘fixture1’,‘fixture2’)
九、pytest跳过测试用例skip、skipif
9.1、@pytest.mark.skip
跳过执行测试用例,有可选参数 reason:跳过的原因,会在执行结果中打印
9.2、pytest.skip()函数基础使用
作用:在测试用例执行期间强制跳过不再执行剩余内容
类似:在Python的循环里面,满足某些条件则break 跳出循环
9.3、 pytest.skip(msg=“”,allow_module_level=False)
当 allow_module_level=True 时,可以设置在模块级别跳过整个模块
9.4、 pytest.skip(msg=“”,allow_module_level=False)
方法:
skipif(condition, reason=None)
参数:
condition:跳过的条件,必传参数
reason:标注原因,必传参数
使用方法:
@pytest.mark.skipif(condition, reason=“xxx”)
9.5、跳过标记

9.6、pytest.importorskip( modname: str, minversion: Optional[str] = None, reason: Optional[str] = Nonse )
作用:如果缺少某些导入,则跳过模块中的所有测试
参数列表
pexpect = pytest.importorskip("pexpect", minversion="0.3")
@pexpect
def test_import():
print("test")
9.7、使用自定义标记 mark
命令运行:
十、Pytest参数化 @pytest.mark.parametrize
pytest允许在多个级别启用测试化参数:
1)pytest.fixture()允许fixture有参数化功能
2)pytest.mark.parametrize 允许在测试函数和类中定义多组参数和fixtures
3)pytest_generate_tests允许定义自定义参数化方案或扩展
10.1、函数数据参数化
方便测试函数对测试属于的获取。
方法:
parametrize(argnames, argvalues, indirect=False, ids=None, scope=None)
常用参数:
argnames:参数名
argvalues:参数对应值,类型必须为list
当参数为一个时格式:[value]
当参数个数大于一个时,格式为:[(param_value1,param_value2…),(param_value1,param_value2…)]
使用方法:
@pytest.mark.parametrize(argnames,argvalues)
️ 参数值为N个,测试方法就会运行N次
十一、pytest标记为失败函数和失败重试
安装第三方插件:pytest-rerun、pytest-rerunfailures
失败重试:【–reruns=1】,用例执行失败后,会立即开始重试一次此用例,再执行下一条用例
失败重运行:【–if】 ,用例集或用例执行完成之后,再次pytest.main(),会收集失败的用例,再次运行;如果没有失败的用例,会执行全部
一个run文件,可以同时写多条pytest.main(),执行pytest的命令
注意:如果用例数较多,第一次运行全部成功的情况,第二个pytest.main(),是会收集所有的用例再执行一遍;建议使用失败重试次数(–reruns=1),失败一次后,立刻执行一次,也可减少用例的失败率
失败重试方式:
1、可在命令行 –reruns=1 reruns_delay=2 失败后重运行1次,延时2s
2、使用装饰器进行失败重运行
@pytest.mark.flaky(reruns=1, reruns_delay=2)
使用方式:
命令行参数:–reruns n(重新运行次数),–reruns-delay m(等待运行秒数)
装饰器参数:reruns=n(重新运行次数),reruns_delay=m(等待运行秒数)
重新运行指定的测试用例:
注意:
1.如果指定了用例的重新运行次数,在命令行添加的 –reruns 对这些用例是不会生效的
2.不可以和 fixture 装饰器@pytest.fixture()一起使用
3.该插件与 pytest-xdist 的 –looponfail 标志不兼容
4.该插件与核心 –pdb 标志不兼容
十二、pytest生成测试报告
1、下载Allure插件
官方地址:allure官方下载地址,bin目录放到path变量当中
验证是否安装成功:allure — version
2、生成临时的json报告(过度)
pytest.ini文件中,addopts中加上一个–alluredir=./temps
–clean-alluredir 清除上次的数据
3、生成html报告
pytest框架自带一个测试报告,内容也相对全面,但是可读性差点,allure生成的测试报告,可改造性强,看起来也美观
4、allure测试报告优化
在allure测试报告页面可以选择中英文切换,我个人比较倾向使用【功能/Behaviors】这个菜单里面的信息,因为这里可以看到更多详细的内容,也比较容易对我们的测试用例进行规范化
1、增加功能模块描述、测试点描述及测试步骤
方法:先import allure,然后在类上添加装饰器@allure.feature("生成账单"),在方法上添加装饰器@allure.story("批量生成账单"),在方法里面添加步骤with allure.step("1.进入[社区管理]菜单"):
使用及效果图:
(feature相当于一个功能,一个大的模块,将case分类到某个feature中,报告中在behaviore中显示,相当于testsuite)
(story相当于对应这个功能或者模块下的不同场景,分支功能,属于feature之下的结构,报告在features中显示,相当于testcase)
2、执行断言,失败截图、成功截图
一条case可以在中间步骤进行断言,可以在最后进行断言,看测试需要。我们想要的一个结果是断言失败的截图并放到allure测试报告中。
现在项目下面建一个screenshot文件夹,用来放截取的图片,然后allure再获取该图片。houseInfoFail.png这个是自己定义的图片的文件名。
如果断言成功了,也截取一张图片,并放到allure报告中。完整代码如下:
houseInfo.png这个是执行成功截取的图片,注意和上面执行失败截取的图片文件名区分一下。
十三、pytest中管理日志
1、日志级别
默认生成的root logger的level是logging.WARNING,低于该级别的就不输出了
级别排序:CRITICAL > ERROR > WARNING > INFO > DEBUG
debug : 打印全部的日志,详细的信息,通常只出现在诊断问题上
info : 打印info,warning,error,critical级别的日志,确认一切按预期运行
warning : 打印warning,error,critical级别的日志,一个迹象表明,一些意想不到的事情发生了,或表明一些问题在不久的将来(例如。磁盘空间低”),这个软件还能按预期工作
error : 打印error,critical级别的日志,更严重的问题,软件没能执行一些功能
critical : 打印critical级别,一个严重的错误,这表明程序本身可能无法继续运行
这时候,如果需要显示低于WARNING级别的内容,可以引入NOTSET级别来显示:
2、分析解释
Logging.Formatter:这个类配置了日志的格式,在里面自定义设置日期和时间,输出日志的时候将会按照设置的格式显示内容。
Logging.Logger:Logger是Logging模块的主体。
进行以下三项工作:
常用函数有:
常用函数有:
3、日志输出-控制台
上面代码通过logging.basicConfig函数进行配置了日志级别和日志内容输出格式
4、日志输出-文件
5、日志输出-控制台和文件
只要在输入到日志中的第二步和第三步插入一个handler输出到控制台:
创建一个handler,用于输出到控制台
ch = logging.StreamHandler()
ch.setLevel(logging.WARNING) # 输出到console的log等级的开关
第四步和第五步分别加入以下代码即可
ch.setFormatter(formatter)
logger.addHandler(ch)
6、format常用格式说明
-
%(levelno)s: 打印日志级别的数值
-
%(levelname)s: 打印日志级别名称
-
%(pathname)s: 打印当前执行程序的路径,其实就是sys.argv[0]
-
%(filename)s: 打印当前执行程序名
-
%(funcName)s: 打印日志的当前函数
-
%(lineno)d: 打印日志的当前行号
-
%(asctime)s: 打印日志的时间
-
%(thread)d: 打印线程ID
-
%(threadName)s: 打印线程名称
-
%(process)d: 打印进程ID
-
%(message)s: 打印日志信息
7、捕捉异常traceback记录

需要将日志不上报错误,仅记录,可以写成exc_info=False
8、日志滚动和过期删除(按时间)
说明:
十四、总结
如果你看到了总结,那么恭喜你看到了总结,总结是全文的精华,而精华是全文的内容。相对Unittest框架,优先选择Pytest。希望此文对你有所帮助,谢谢关注和点赞收藏。
作者:@逝水流年轻染尘@