2.4 mark 标记被测函数
以下是mark的一些内置结构的标记物:
usefixtures - 在测试功能或类上使用固定装置filterwarnings - 过滤了一个测试函数的某些警告skip - 始终跳过一个测试函数skipif - 如果满足某个条件,则跳过一个测试函数xfail - 如果满足某一条件,则产生“预期失败”结果parametrize - 对同一个测试函数执行多个调用。- 创建自定义标记或将标记应用于整个测试类或模块都很容易。这些标记可以被插件使用,也通常用于在使用-m选项的命令行上选择测试。
注意:mark标记只能应用于被测函数,对固定装置没有影响
2.4.1 注册标记
您可以像这样在您的pytest.ini文件中注册自定义标记:
[pytest]
markers =
slow: marks tests as slow (deselect with '-m "not slow"')
serial
2.4.2 引发未知标记上的错误
添加addopts = --strict-markers ,项目中只要有未知的标记,执行就会报错,如下设置:
[pytest]
addopts = --strict-markers
markers =
slow: marks tests as slow (deselect with '-m "not slow"')
serial
2.5 参数化固定装置、测试函数
Pytest可以在以下几个级别上实现测试参数化:
pytest.fixture() 允许 parametrize fixture functions@pytest.mark.parametrize 定义多组参数、固定装置在测试函数、类上面pytest_generate_tests 允许用户定义自定义参数化方案或扩展。
2.5.1 参数化测试函数:@pytest.mark.parametrize
2.5.1.1 @parametrize 装饰器定义了三个不同的元组
@parametrize 装饰器定义了三个不同的(test_input,expected) 元组,以便test_eval 函数将依次使用它们运行三次:
import pytest
@pytest.mark.parametrize("test_input,expected", [("3+5", 8), ("2+4", 6), ("6*9", 42)])
def test_eval(test_input, expected):
assert eval(test_input) == expected
C:\Users\Desktop\python>pytest test_expectation.py
================================================== test session starts ===================================================
platform win32 -- Python 3.8.0, pytest-6.2.5, py-1.11.0, pluggy-1.0.0
rootdir: C:\Users\X21201\Desktop\python
collected 3 items
test_expectation.py ..F [100%]
======================================================== FAILURES ========================================================
___________________________________________________ test_eval[6*9-42] ____________________________________________________
test_input = '6*9', expected = 42
@pytest.mark.parametrize("test_input,expected", [("3+5", 8), ("2+4", 6), ("6*9", 42)])
def test_eval(test_input, expected):
> assert eval(test_input) == expected
E AssertionError: assert 54 == 42
E + where 54 = eval('6*9')
test_expectation.py:7: AssertionError
================================================ short test summary info =================================================
FAILED test_expectation.py::test_eval[6*9-42] - AssertionError: assert 54 == 42
============================================== 1 failed, 2 passed in 0.07s ===============================================
2.5.1.2 在类或模块上使用参数化标记
import pytest
@pytest.mark.parametrize("n,expected", [(1, 2), (3, 4)])
class TestClass:
def test_simple_case(self, n, expected):
assert n + 1 == expected
def test_weird_simple_case(self, n, expected):
assert (n * 1) + 1 == expected
collected 4 items
test_expectation.py::TestClass::test_simple_case[1-2] PASSED
test_expectation.py::TestClass::test_simple_case[3-4] PASSED
test_expectation.py::TestClass::test_weird_simple_case[1-2] PASSED
test_expectation.py::TestClass::test_weird_simple_case[3-4] PASSED
2.5.1.3 参数化一个py文件中所有测试
import pytest
pytestmark = pytest.mark.parametrize("n,expected", [(1, 2), (3, 4)])
class TestClass:
def test_simple_case(self, n, expected):
assert n + 1 == expected
def test_weird_simple_case(self, n, expected):
assert (n * 1) + 1 == expected
class TestDemo:
def test_simple_case_001(self, n, expected):
assert n + 1 == expected
collected 6 items
test_expectation.py::TestClass::test_simple_case[1-2] PASSED
test_expectation.py::TestClass::test_simple_case[3-4] PASSED
test_expectation.py::TestClass::test_weird_simple_case[1-2] PASSED
test_expectation.py::TestClass::test_weird_simple_case[3-4] PASSED
test_expectation.py::TestDemo::test_simple_case_001[1-2] PASSED
test_expectation.py::TestDemo::test_simple_case_001[3-4] PASSED
2.5.1.4 参数化中标记单个测试实例:使用 mark.xfail:
import pytest
@pytest.mark.parametrize("test_input,expected",[("3+5", 8), ("2+4", 6), pytest.param("6*9", 42, marks=pytest.mark.xfail)],)
def test_eval(test_input, expected):
assert eval(test_input) == expected
collected 3 items
test_expectation.py::test_eval[3+5-8] PASSED
test_expectation.py::test_eval[2+4-6] PASSED
test_expectation.py::test_eval[6*9-42] XFAIL
2.5.1.5 参数的所有组合:堆叠参数化装饰器
import pytest
@pytest.mark.parametrize("x", [0, 1])
@pytest.mark.parametrize("y", [2, 3])
def test_foo(x, y):
pass
collected 4 items
test_expectation.py::test_foo[2-0] PASSED
test_expectation.py::test_foo[2-1] PASSED
test_expectation.py::test_foo[3-0] PASSED
test_expectation.py::test_foo[3-1] PASSED
2.5.2 pytest_generate_tests 示例
有时,您可能想要实现您自己的参数化方案,或实现一些动态来确定一个设备的参数或范围。为此,您可以使用在收集测试函数时调用的pytest_generate_tests钩子
def pytest_addoption(parser):
parser.addoption(
"--stringinput",
action="append",
default=[],
help="list of stringinputs to pass to test functions",
)
def pytest_generate_tests(metafunc):
if "stringinput" in metafunc.fixturenames:
metafunc.parametrize("stringinput", metafunc.config.getoption("stringinput"))
def test_valid_string(stringinput):
assert stringinput.isalpha()
执行测试,动态指定参数:
pytest --stringinput="hello" --stringinput="world" test_strings.py -vs
pytest -q -rs test_strings.py
|