1. 通过python -m pytest
调用pytest
你可以通过python的解释器来执行测试:
python -m pytest [...]
但是,这和直接执行pytest [...]
命令的效果几乎是一模一样的;
2. pytest
执行结束时返回的状态码
pytest
命令执行结束,可能会返回以下六种状态码:
- 0:(OK)所有收集到的用例测试通过
- 1:(TESTS_FAILED)有用例测试失败
- 2:(INTERRUPTED)用户打断测试执行
- 3:(INTERNAL_ERROR)测试执行的过程中,发生内部错误
- 4:(USAGE_ERROR)
pytest
命令使用错误 - 5:(NO_TESTS_COLLECTED)没有收集到测试用例
它们在枚举类 _pytest.main.ExitCode 中声明。并且,其作为公开API的一部分,能够直接引入和访问:
from pytest import ExitCode
3. 获取帮助信息
pytest --version # 查看版本号和pytest的引入路径 pytest -h # 查看帮助信息
4. 最多允许失败的测试用例数
当达到最大上限时,退出执行;如未配置,则没有上限:
pytest -x # 遇到第一个失败时,退出执行 pytest --maxfail==2 # 遇到第二个失败时,退出执行
5. 执行指定的测试用例
pytest
支持多种方式来执行特定的测试用例:
5.1. 执行指定模块中的测试用例
pytest test_mod.py
5.2. 执行指定目录下所有的测试用例
pytest testing/
5.3. 执行文件名、类名或者函数名中包含特定关键字的测试用例
执行当前目录下,名字包含_class
但不包含two
的测试用例:
pytest -k "_class and not two" .
注意:python的关键字不可以应用在
-k
选项中,例如,class
、def
等。
5.4. 执行指定nodeid
的测试用例
pytest
为每一个收集到的测试用例指定一个唯一的nodeid
。其由模块名加说明符构成,中间以::
间隔。
其中,说明符可以是类名、函数名以及由parametrize
标记赋予的参数:
# src/chapter-2/test_nodeid.py import pytest def test_one(): print('test_one') assert 1 class TestNodeId: def test_one(self): print('TestNodeId::test_one') assert 1 @pytest.mark.parametrize('x,y', [(1, 1), (3, 4)]) def test_two(self, x, y): print(f'TestNodeId::test_two::{x} == {y}') assert x == y
在上述示例中,我们创建了三个测试用例,分别对应不同的说明符:
-
指定函数名执行
$ pipenv run pytest -q -s src/chapter-2/test_nodeid.py::test_one test_one . 1 passed in 0.01s
-
指定类名+函数名执行
$ pipenv run pytest -q -s src/chapter-2/test_nodeid.py::TestNodeId::test_one TestNodeId::test_one . 1 passed in 0.01s
-
指定由
parametrize
标记赋予的参数执行$ pipenv run pytest -q -s src/chapter-2/test_nodeid.py::TestNodeId::test_two[1-1] TestNodeId::test_two::1 == 1 . 1 passed in 0.01s
这里对参数
x
、y
赋值的形式是[1-1]
,中间以-
间隔;单个或多个参数的赋值形式以此类比;并且,只能为
[1-1]
或者[3-4]
,其它的会报错;
注意:
这里我们也可以使用
-k
选项达到同样的效果:
首先,可以使用
--collect-only
选项查看用例名:λ pipenv run pytest -q -s --collect-only src/chapter-2/test_nodeid.py test_nodeid.py::test_one test_nodeid.py::TestNodeId::test_one test_nodeid.py::TestNodeId::test_two[1-1] test_nodeid.py::TestNodeId::test_two[3-4]
然后,使用
-k
执行符合规则的用例,例如:执行test_nodeid.py::test_one
:λ pipenv run pytest -q -s -k 'test_one and not TestNodeId' src/chapter-2/test_nodeid.py test_one . 1 passed, 3 deselected in 0.02s
结果和执行
pipenv run pytest -q -s src/chapter-2/test_nodeid.py::test_one
一样;
5.5. 执行指定标记的用例
pytest -m slow
5.6. 执行指定包中的测试用例
pytest --pyargs pkg.testing
pytest
会引入pkg.testing
包,并在它的系统目录下搜寻测试用例并执行;
6. 修改回溯信息的输出模式
pytest回溯信息的输出一共有六种模式:auto/long/short/line/native/no,用--tb
选项指定:
pytest -l, --showlocals # 打印本地变量 pytest --tb=auto # 默认模式 pytest --tb=long # 尽可能详细的输出 pytest --tb=short # 更简短的输出 pytest --tb=line # 每个失败信息总结在一行中 pytest --tb=native # python的标准输出 pytest --tb=no # 不打印失败信息
--full-trace
是一种比--tb=long
更详细的输出模式。它甚至能观察到用户打断执行(Ctrl+C
)时的回溯信息,而上述六种模式默认是不输出此类信息的。
7. 总结报告
-r
选项可以在执行结束后,打印一个简短的总结报告。在执行的测试用例很多时,可以让你对结果有个清晰的了解:
# src/chapter-2/test_report.py
import pytest
@pytest.fixture
def error_fixture():
assert 0
def test_ok():
print("ok")
def test_fail():
assert 0
def test_error(error_fixture):
pass
def test_skip():
pytest.skip("skipping this test")
def test_xfail():
pytest.xfail("xfailing this test")
@pytest.mark.xfail(reason="always xfail")
def test_xpass():
pass
$ pipenv run pytest -q -rA src/chapter-2/test_report.py
.FEsxX [100%]
================================ ERRORS =================================
_____________________ ERROR at setup of test_error ______________________
@pytest.fixture
def error_fixture():
> assert 0
E assert 0
src/chapter-2/test_report.py:27: AssertionError
=============================== FAILURES ================================
____________