1. pytest基础功能
命名规则
文件名以test_*.py文件和*_test.py
以test_开头的函数
以Test开头的类, 注意:类不能包含__init__构造函数
以test_开头的方法
所有的包pakege必须要有__init__.py文件
常用命令
pytest --help # 查看帮助
cmd执行pytest用例有三种方法
pytest 或 py.test 或 python -m pytest
setup和teardown实现
- 模块级(setup_module/teardown_module)开始于模块始末,全局的
- 函数级(setup_function/teardown_function)只对函数用例生效(不在类中)
- 类级(setup_class/teardown_class)只在类中前后运行一次(在类中)
- 方法级(setup_method/teardown_method)开始于方法始末(在类中)
- 类里面的(setup/teardown)运行在调用方法的前后
- @pytest.fixture 装饰器实现, 通过scope 参数指定作用范围
用例执行:
pytest folderpath # 执行该文件夹内所有测试文件用例
pytest test_demo.py #执行当前文件test_demo内所有用例
pytest test_demo.py::TestClass #执行当前类 TestClass 内所有用例
pytest test_demo.py::TestClass::test_01 # 执行类中名为test_01 的用例
重复执行
pytest-repeat 安装 pip install pytest-repeat
使用--count命令行选项指定要运行测试用例和测试次数, 不带该参数默认执行一次
pytest test_demo.py -s --count=5
--repeat-scope类似于pytest fixture的scope参数,--repeat-scope也可以设置参数: session
, module
,class
或者function
(默认值)
function
(默认)范围针对每个用例重复执行,再执行下一个用例class
以class为用例集合单位,重复执行class里面的用例,再执行下一个module
以模块为单位,重复执行模块里面的用例,再执行下一个session
重复整个测试会话,即所有收集的测试执行一次,然后所有这些测试再次执行等等
使用--repeat-scope=session
重复执行整个会话用例
pytest test_demo.py -s --count=5 --repeat-scope=session
如果要在代码中标记要重复多次的测试,可以使用@pytest.mark.repeat(count)
装饰器 count 为重复执行的次数
fixture
text fixtures的目的是为测试的重复执行提供一个可靠的固定基线。 pytest fixture比经典的xUnit setUp/tearDown方法有着显着的改进:
- fixtures具有明确的名称,在测试用例/类/模块或整个项目中通过声明使用的fixtures名称来使用。
- fixtures以模块化方式实现,因为每个fixture名称都会触发调用fixture函数,该fixture函数本身可以使用其它的fixtures。
- 从简单的单元测试到复杂的函数测试,fixtures的管理允许根据配置和组件选项对fixtures和测试用例进行参数化,或者在测试用例/类/模块或整个测试会话范围内重复使用该fixture。
此外,pytest继续支持经典的xUnit风格的setup方法。 你可以根据需要混合使用两种样式,逐步从经典样式移动到新样式。 你也可以从现有的unittest.TestCase样式或基于nose的项目开始。
scope参数的可选值包括:function(函数),class(类),module(模块),package(包)及 session(会话)。
fixture 执行顺序
@pytest.fixture(scope="session")
def s1():pass@pytest.fixture(scope="module")
def m1():pass@pytest.fixture
def f1(tmpdir):pass@pytest.fixture
def f2():passdef test_foo(f1,m1,f2,s1):...
test_foo
中fixtures将按以下顺序执行:
- s1:是最高范围的fixture(会话级)
- m1:是第二高的fixture(模块级)
- tmpdir:是一个函数级的fixture,f1依赖它,因此它需要在f1前调用
- f1:是test_foo参数列表中第一个函数范围的fixture。
- f2:是test_foo参数列表中最后一个函数范围的fixture。
yield和addfinalizer
如果在设置代码期间(yield关键字之前)发生异常,则不会调用teardown代码(在yield之后)。 执行teardown代码的另一种选择是利用请求上下文对象的addfinalizer
方法来注册teardown函数。
yield
和addfinalizer
方法在测试结束后调用它们的代码时的工作方式类似,但addfinalizer
相比yield
有两个主要区别:
- 使用
addfinalizer
可以注册多个teardown函数。 - 无论fixture中setup代码是否引发异常,都将始终调用teardown代码。 即使其中一个资源无法创建/获取,也可以正确关闭fixture函数创建的所有资源
用例等级
@allure.severity装饰器按严重性级别来标记case 如 @allure.severity("normal")
执行指定测试用例 --allure-severities blocker
BLOCKER = 'blocker' 阻塞缺陷
CRITICAL = 'critical' 严重缺陷
NORMAL = 'normal' 一般缺陷
MINOR = 'minor' 次要缺陷
TRIVIAL = 'trivial' 轻微缺陷
用例标记
@pytest.mark 使用pytest.mark
你可以轻松地在测试用例上设置元数据。 如 @pytest.mark.A A即用例的标记
常用的内置标记:
- skip - 始终跳过该测试用例
- skipif - 遇到特定情况跳过该测试用例
- xfail - 遇到特定情况,产生一个“期望失败”输出
- parametrize - 在同一个测试用例上运行多次调用( 参数化数据驱动)
当使用--strict
命令行参数时,未在pytest.ini
文件中注册的任何标记都将引发异常
选择指定标记用例执行
`
pytest -m A
pytest -m "A and B"
pytest -m "(A and B) or C"
pytest.ini
1.pytest.ini的放置位置:一般放在项目工程的根目录(即当前项目的顶级文件夹下)
2.pytest.ini的作用:指定pytest的运行方式(在cmd输入pytest后,会读取pytest.ini中的配置信息,按指定的方式去运行)
3.cmd下使用 pytest -h 命令查看pytest.ini的设置选项
在 pytest.ini 中可以添加adopt参数,可以更改默认命令行选项,这个当在cmd输入一堆指令去执行用例时,可以用该参数代替
[pytest]
markers =A: this is weibo pageB: toutiao pageC: xinlang page
# 命令行参数
addopts = -v --reruns=1 --count=2 --html=reports.html --self-contained-html -n=auto
-v 指定的函数节点id
如果想指定运行某个.py模块下,类里面的一个用例,如:TestClass里面test_method用例 每个test_开头(或_test结尾)的用例,函数(或方法)的名称就是用例的节点id,指定节点id运行用-v 参数
-k 匹配用例名称
可以使用-k命令行选项指定在匹配用例名称的表达式
-k "test_func_01 or test_func_02" # 使用or, 用例必须全名
-k "02"
-k "func"
-k "not 02"
输出捕获
--capture=no 实时输出log信息
在测试执行期间,程序中的标准输出/标准错误输出都会被捕获到。 如果测试或setup方法执行失败时,会在报错追溯信息中查看到程序中的标准输出及标准错误输出。(可以通过--show-capture
命令行选项配置是否捕获程序中的标准输出/标准错误输出)。
此外,stdin
被设置为“null”对象,测试运行过程中无法从中读取数据,因为在运行自动化测试时很少需要等待交互式输入。
捕获默认是通过拦截对低优先级文件描述符的写入来完成的。 这允许捕获简单print语句的输出以及测试启动的子进程的输出。
pytest
可以通过两种方式捕获输出:
- 文件描述符(FD)级别捕获(默认):将捕获进入操作系统文件描述符1和2的所有写入。
sys
级别捕获:仅捕获Python文件sys.stdout
和sys.stderr
。 不执行对文件描述符的写入捕获。
pytest -s # 禁止捕获所有输出
pytest --capture=sys # 使用in-mem文件代替sys.stdout/stderr with
pytest --capture=fd # 同时将filedescriptors 1和2指向临时文件
doc 测试
doctest从字面意思上看,那就是文档测试。doctest是python里面自带的一个模块,它实际上是单元测试的一种。 官方解释:doctest 模块会搜索那些看起来像交互式会话的 Python 代码片段,然后尝试执行并验证结果
doctest测试用例可以放在两个地方
- 函数或者方法下的注释里面
- 模块的开头
doctest内容也可以和代码抽离开,单独用一个.txt文件(默认)保存
默认情况下,Pytest按照python doctest
模块标准test*.txt
模式进行匹配。也可以通过使用--doctest-glob
命令更改匹配模式,--doctest-glob
可以在命令行中多次使用, 如
pytest --doctest-glob='*.rst'
用例skip
pytest.mark.skip可以标记无法在某些平台上运行的测试功能,或者希望失败的测试功能
跳过测试函数的最简单方法是使用跳过装饰器标记它
@pytest.mark.skip(reason="no way of currently testing this")
有条件跳过用例
@pytest.mark.skipif(3 < 4)
测试报告
pytest可以生成junit格式的xml报告,在命令行中加入--junit-xml=path
参数就可以了。path为待生成xml文件路径
生成xml
pytest --junit-xml=report.xml
生成 html
pytest --html=report.html
2. 测试常用pytest插件
失败重试
在做测试的时候我们通常会遇到网络波动,这事我们需要做失败重试机制,确认失败后才进行失败告警或者在报告中体现
在pytest中,我们通常会使用安装pytest-rerunfailures来进行失败重试
pip install -U pytest-rerunfailures
在命令行中增加 –reruns NUM,NUM为失败重试的最大次数
pytest test_se.py --reruns 3
重复运行
pip install pytest-repeat
在执行命令中添加–count=NUM NUM为每条用例需要执行的次数
pytest test_se.py --count=3
并行运行
pip install pytest-xdist
pytest-xdist插件的 -n numprocesses 选项可以指定运行测试的处理器进程数,-n auto选项可以自动侦测系统里的CPU数码
pytest -n 3 test_test.py pytest -n auto test_test.py
设定执行顺序
pip install pytest-ordering
根据order参数从小到大执行
@pytest.mark.run(order=2) def test_order1():print ("first test")assert True @pytest.mark.run(order=1) def test_order2():print ("second test")assert True
测试时间限制
在正常时间下,pytest是没有测试时间限制的,但有时候需要控制测试用例执行执行,可以使用pytest-timeout。
pip install pytest-timeout
在命令行中添加 –timeout=X,X为该条命令执行的总时间限制,单位秒
pytest --timeout=3.5 test_xxx.py