本文参考了官方文档和一些乐于分享的大佬的博客,结合自己的理解完成。学习pytest框架的小白,需要按照教程自己敲一遍,配置一遍,摸索一下整个框架的运行逻辑,数据流的走向,文字虽多,请细细看完,有问题欢迎在群里提出,相互学习,互相指正。希望大家有所收获,学有所得。(群:自动化测试-夜行者:816489363)
--成都-阿木木
官方文档:https://docs.pytest.org/en/latest/contents.html
感谢慕城南风的博客:https://blog.csdn.net/lovedingd/article/details/98952868
Pytest支持的插件库:https://plugincompat.herokuapp.com/
第三方插件库:https://docs.pytest.org/en/latest/plugins.html
pytest兼容以前的unittest,只需要少量的更改代码即可,下面就大家熟悉的setup、teardown以及html报告进行说明
setup和teardown主要分为:类级、函数级。
运行于测试方法前后:
运行结果:
运行于测试类的始末:
使用pytest的测试报告插件可以替换unittest本身的HTMLTestRunner报告
安装:pip install pytest-html
使用方式:命令行格式:pytest --html=用户路径/report.html
所有的单测文件名都需要满足test_*.py格式或*_test.py格式。
在单测文件中,测试类以Test开头,并且不能带有 init 方法(注意:定义class时,需要以T开头,不然pytest是不会去运行该class的)
在单测类中,可以包含一个或多个test_开头的函数。
此时,在执行pytest命令时,会自动从当前目录及子目录中寻找符合上述约束的测试函数来执行。可以在pytest.ini中修改测试目录、测试模块、测试类、测试方法扫描进行默认修改。
程序运行成功结束控制台输出:Process finished with exit code 0
Exit code 0 所有用例执行完毕,全部通过
Exit code 1 所有用例执行完毕,存在Failed的测试用例
Exit code 2 用户中断了测试的执行
Exit code 3 测试执行过程发生了内部错误
Exit code 4 pytest 命令行使用错误
Exit code 5 未采集到可用测试用例文件
fixture修饰器来标记固定的工厂函数,在其他函数,模块,类或整个工程调用它时会被激活并优先执行,通常会被用于完成预置处理和重复操作。
fixture是在测试函数前后运行,由pytest执行的外壳函数;代码可以定制,满足多变的测试需求,包括定义传入测试中的数据集,配置测试前系统的初始工作,为批量测试提供数据源等等,fixture是pytest用于将测试前后进行预备,清理工作的代码分离出核心测试逻辑的一种机制
@pytest.fixture()装饰器用于申明函数是一个fixture,如果测试函数的参数列表中包含fixture,那么pytest会检测到,检测顺序是,优先搜索该测试所在的模块,然后搜索conftest.py,并在测试函数运行之前执行该fixture,fixture可以完成测试任务,也可以返回测试数据给测试函数
scope:被标记方法的作用域
function" (default):作用于每个测试方法,每个test都运行一次
"class":作用于整个类,每个class的所有test只运行一次
"module":作用于整个模块,每个module的所有test只运行一次
"session:作用于整个session(慎用),每个session只运行一次
params:(list类型)提供参数数据,供调用标记方法的函数使用
autouse:是否自动运行,默认为False不运行,设置为True自动运行
pytest --setup-show test_example1.py(可以看到执行过程顺序)
A.返回测试数据
function每个函数或方法都会调用(有两种写法,不传递参数,默认就是function,也可以指定scope="function",来进行作用域的指定
session是多个文件调用一次,可以跨越.py文件调用,每个.py文件都是module
当我们有多个.py文件的用例时,如果多个用例只需要调用一次fixture,可以设置scope="session",并且写入到conftest。py文件里面
1、pytest.ini:pytest的主配置文件,可以改变pytest的默认行为,其中有很多可以配置的选项,包含日志,命令行的一些参数,控制台输出的信息等等
2、conftest.py:是本地的插件库,其中的hook函数和fixture将作用于该文件所在目录以及所有子目录
使用pytest --help查看pytest.ini所有设置选项
pytest -v --verbose 可以输出详细信息
[pytest]
addops = -v --alluredir ./allure-result(addopts增加默认执行的操作步骤,简化命令行参数)(allure测试报告默认在json文件目录下生成,可以使用allure generate jsonpathdir -o allurepathdir更改)
ps:
如何使用allure生成测试报告
1、brew install allure
2、安装allure-pytest
3、运行case时增加命令行选项pytest -v --allure ./allure-results test.py
4、生成测试报告allure generate allure-results -o allure
有哪些常用的命令行选项呢?
-v:输出详细信息,显示具体执行了那些测试用例
--collect-only 展示在给定的配置下那些测试用例会被执行,仅用于展示,不执行
-k 允许使用表达式指定希望运行的测试用例
exp:pytest -v -k 'baidu' test.py(在pytest中查找含有baidu关键字的case执行)
-m marker用于标记测试并分组
--strict 遇到mark拼写错误会检查,与mark配合使用
自定义标记可以简化测试工作,但是标记容易拼写错误,默认情况下不会引起错误,pytest以为这是另外一个标记,为了避免拼写错误,可以在pytest.ini文件里进行注册
markers = data_file:a test_data get_and_format marker
通过命令查看:pytest --help(或者pytest --marks)没有注册的标记不会出现在markers列表里面,如果使用--strict选项,遇到拼写错误的标记或者未注册的标记会报错
如果自己增加一个测试函数的标记呢?
@pytest.mark.smoke
pytest -m 'smoke' test.py
minversion = 6.0
minversion选项可以指定运行测试用例的pytest的最低版本
norecursedirs = .*data config utils
可以使用norecursedirs缩小pytest的搜索范围
指定访问目录
testpath = testsdir
通过将log_cli配置选项设置为true,pytest将在直接将日志记录发送到控制台时输出日志记录。
您可以指定传递的级别,以将等于或更高级别的日志记录打印到控制台的日志记录级别--log-cli-level。此设置接受python文档中显示的日志记录级别名称,或者接受整数作为日志记录级别num。
此外,您还可以指定--log-cli-format和 --log-cli-date-format哪个镜和默认--log-format和 --log-date-format如果没有提供,但只被应用到控制台日志处理程序。
还可以在配置INI文件中设置所有CLI日志选项。选项名称为:
log_cli_level
log_cli_format
log_cli_date_format
如果您需要将整个测试套件的日志记录记录到一个文件中,则可以传递 --log-file=/path/to/log/file。该日志文件以写模式打开,这意味着它将在每个运行测试会话中被覆盖。
您还可以通过传递日志文件的日志记录级别 --log-file-level。此设置接受python文档中所见的日志记录级别名称(即大写的名称),或者接受整数作为日志记录级别num。
此外,您还可以指定--log-file-format和 --log-file-date-format,它们等于--log-format和 --log-date-format但应用于日志文件日志处理程序。
还可以在配置INI文件中设置所有日志文件选项。选项名称为:
log_file
log_file_level
log_file_format
log_file_date_format
您可以调用set_log_path()以动态自定义log_file路径。此功能被认为是实验性的。
#配置pytest命令行运行参数
[pytest]
addopts = -s ... # 空格分隔,可添加多个命令行参数 -所有参数均为插件包的参数配置测试搜索的路径
testpaths = ./scripts # 当前目录下的scripts文件夹 -可自定义
#配置测试搜索的文件名称
python_files = test*.py
#当前目录下的scripts文件夹下,以test开头,以.py结尾的所有文件 -可自定义
配置测试搜索的测试类名
python_classes = Test_*
#当前目录下的scripts文件夹下,以test开头,以.py结尾的所有文件中,以Test开头的类 -可自定义
配置测试搜索的测试函数名
python_functions = test_*
#当前目录下的scripts文件夹下,以test开头,以.py结尾的所有文件中,以Test开头的类内,以test_开头的方法 -可自定义
@pytest.mark.parametrize(argnames,argvalues)装饰器可以达到批量传送参数的目的,argvalues里面传递的是元组或者列表里面嵌套元组的方式
pytest可以通过添加插件可以扩展功能,pytest的代码结构适合定制和扩展插件,可以借助hook函数来实现。把fixture函数或者hook函数添加到conftest文件里,这种方式,就已经创建了一个本地的conftest插件!!!
1、内置plugins:从代码内部的_pytest目录加载;
2、外部插件(第三方插件):通过setuptools entry points机制发现的第三方插件模块;
推荐使用的第三方的pytest插件:https://docs.pytest.org/en/latest/plugins.html
3、conftest.py形式的本地插件:测试目录下的自动模块发现机制
通过pytest --trace-config命令可以查看当前pytest中所有的plugin
在pytest中,所谓的plugin其实就是能被pytest发现的一些带有pytest hook方法的文件或者对象
使用的框架提供公用的规则,其他开发者使用这个规则编写的文件或者代码可以被框架识别,框架进行初始化时,会收集满足这个规则的所有代码(文件),然后将这些代码加入到框架中来,在执行时,一并进行初始化。所有这一规则下可以被框架收集到的方法就是hook方法。
插件可以改变pytest行为,可用的hook函数很多,详细的定义:
http://doc.pytest.org/en/latest/_modules/_pytest/hookspec.html
1、pytest_addoption,基本每个pytest plugin都会有这个hook方法,它的作用是为pytest命令添加自定义的参数
parser:用户命令行参数与ini文件值的解析器
def pytest_addoption(parser):
parser.addoption("--env",##注册一个命令行选项
default="test",#默认值为test
dest="env",
help="set test run env")#说明
pytest_addoption:Hook function,这里创建了一个argparser的group,通过addoption方法添加option,使得显示help信息时相关option显示在一个group下面,更加友好,使用pytest --help可以查看
2、pytest_collection_modifyitems,是一个完成所有测试项的收集后,pytest调用的钩子
def pytest_collection_modifyitems(items):
pass
测试用例收集完成后,将收集到的item的name和nodeid的中文显示在控制台上,所有的测试用例收集完毕后调用,可以再次过滤或者对它们重新排序
items(收集的测试项目列表)
根据特定的条件,不执行标识的测试函数.
方法:
skipif(condition, reason=None)
参数:
condition:跳过的条件,必传参数
reason:标注原因,必传参数
使用方法:
@pytest.mark.skipif(condition, reason="xxx")
标记测试函数为失败函数
方法:
xfail(condition=None, reason=None, raises=None, run=True, strict=False)
常用参数:
condition:预期失败的条件,必传参数
reason:失败的原因,必传参数
使用方法:
@pytest.mark.xfail(condition, reason="xx")
方便测试函数对测试属于的获取。
方法:
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 --showlocals # show local variables in tracebacks
pytest -l # show local variables (shortcut)
pytest --tb=auto # (default) 'long' tracebacks for the first and last
# entry, but 'short' style for the other entries
pytest --tb=long # exhaustive, informative traceback formatting
pytest --tb=short # shorter traceback format
pytest --tb=line # only one line per failure
pytest --tb=native # Python standard library formatting
pytest --tb=no # no traceback at all
python --full-trace 参数会打印更多的错误输出信息,比参数 --tb=long 还多,即使是 Ctrl+C 触发的错误,也会打印出来
获取最慢的10个用例的执行耗时
pytest --durations=10
参考夜行者自动化测试群(群号:816489363)文件:pytest-xdist进程级并发参数化说明--成都-阿木木
多重校验插件,可以执行完所有的断言,常规assert断言执行失败后下面的断言便会停止,不在执行,assume插件可以执行完所有断言
安装命令:pip install pytest-assume
使用方式:
Pytest用例默认执行顺序是和collect的顺序一致,用例收集是按照测试目录开始,由上到下,在测试模块中,测试用例收集也是从上到下,需要调整测试函数的执行顺序可以通过pytest_collection_modifyitems这个hook函数(钩子)进行插件编写。在pytest的第三方插件中,已经有人实现了这个功能,下面介绍pytest-ordering这个插件。
安装命令:pip install pytest-ordering
失败重跑插件,使用比较简单,在脚本运行过程中,可能某些原因导致用例执行失败,可能是网络加载等,可以使用该插件,对于失败的用例进行重跑,提高报告的准确性。
安装命令:pip install pytest-rerunfailures
命令行指定:
Pytest -s test_xxx.py --reruns 5 #表示失败用例运行五次
Pytest -s test_xxx.py --reruns-delay 2 #表示失败用例等待2S后在执行
在装饰器中指定:
显示进度条,控制台显示比较好看
显示效果如下:
安装命令:pip install pytest-sugar
(群:自动化测试-夜行者:816489363)