@pytest.mark.parametrize 是 pytest 提供的用于参数化的标记器,在测试函数需要不同测试数据的场景下使用。比如参数的字符类型与长度测试测试。
参数说明
@pytest.mark.parametrize 需要接收两个参数:第一个参数是字符串,里面定义参数变量;第二个参数是一个列表,列表内值是多个元组,元组的数量即是测试用例的执行次数。元组内的值需要与第一个参数字符串定义的变量对应。
比如 @pytest.mark.parametrize(“n,n1,n2”, [(1, 2, 3), (3, 4, 5), (5, 6, 7)]),被装饰得测试用例的参数需为 n,n1,n2 。
被装饰得测试用例会被执行三次。第一次执行, 1 会传给 n,2 会传给 n1,3 会传给 n3;第二次执行, 3 会传给 n,4 会传给 n1,5 会传给 n3;第三次执行, 5 会传给 n,6 会传给 n1,7 会传给 n3。
参数化基本用法
参数化单个测试用例:
import pytest
@pytest.mark.parametrize("n, expected", [
(1 + 2, 3),
(2 + 2, 4),
(3 * 3, 9)
])
def test_math(n, expected):
assert n == expected
运行结果:
======================================================== test session starts ========================================================
platform linux -- Python 3.12.3, pytest-9.0.2, pluggy-1.6.0
configfile: pytest.toml
collected 3 items
cases/test_a.py::test_math[3-3] PASSED [ 33%]
cases/test_a.py::test_math[4-4] PASSED [ 66%]
cases/test_a.py::test_math[9-9] PASSED [100%]
========================================================= 3 passed in 0.01s =========================================================
参数化测试组(组中所有的测试用例都需要被参数化):
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
运行结果:
======================================================== test session starts ========================================================
platform linux -- Python 3.12.3, pytest-9.0.2, pluggy-1.6.0
configfile: pytest.toml
collected 4 items
cases/test_a.py::TestClass::test_one[1-2] PASSED [ 25%]
cases/test_a.py::TestClass::test_one[3-4] PASSED [ 50%]
cases/test_a.py::TestClass::test_two[1-2] PASSED [ 75%]
cases/test_a.py::TestClass::test_two[3-4] PASSED [100%]
========================================================= 4 passed in 0.02s =========================================================
参数化模块中测试用例(模块中所有的测试用例都需要被参数化):
import pytest
pytestmark = pytest.mark.parametrize("n,expected", [(1, 2), (2, 4)])
class TestClass:
def test_one(self, n, expected):
assert n + n == expected
def test_two(self, n, expected):
assert n + n == expected
def test_three(n, expected):
assert n+n == expected
def test_four(n, expected):
assert n+n == expected
运行结果:
======================================================== test session starts ========================================================
platform linux -- Python 3.12.3, pytest-9.0.2, pluggy-1.6.0
configfile: pytest.toml
collected 8 items
cases/test_a.py::TestClass::test_one[1-2] PASSED [ 12%]
cases/test_a.py::TestClass::test_one[2-4] PASSED [ 25%]
cases/test_a.py::TestClass::test_two[1-2] PASSED [ 37%]
cases/test_a.py::TestClass::test_two[2-4] PASSED [ 50%]
cases/test_a.py::test_three[1-2] PASSED [ 62%]
cases/test_a.py::test_three[2-4] PASSED [ 75%]
cases/test_a.py::test_four[1-2] PASSED [ 87%]
cases/test_a.py::test_four[2-4] PASSED [100%]
========================================================= 8 passed in 0.02s =========================================================
组合参数化
可以堆叠 parametrize装饰器,进行参数的组合参数化:
import pytest
@pytest.mark.parametrize("x", [0, 1])
@pytest.mark.parametrize("y", [2, 3])
def test_foo(x, y):
assert y > x
运行结果:
======================================================== test session starts ========================================================
platform linux -- Python 3.12.3, pytest-9.0.2, pluggy-1.6.0
configfile: pytest.toml
collected 4 items
cases/test_a.py::test_foo[2-0] PASSED [ 25%]
cases/test_a.py::test_foo[2-1] PASSED [ 50%]
cases/test_a.py::test_foo[3-0] PASSED [ 75%]
cases/test_a.py::test_foo[3-1] PASSED [100%]
========================================================= 4 passed in 0.01s =========================================================
会按照 x=0/y=2、x=1/y=2、x=0/y=3、x=1/y=3的顺序组合参数化。
参数化中应用标记
可以在 parametrize 中标记单个测试实例,例如自定义的user:
import pytest
@pytest.mark.parametrize(
"n,expected",
[("3+5", 8), ("2+4", 6), pytest.param("6*7", 42, marks=pytest.mark.user)],
)
def test_eval(n, expected):
assert eval(n) == expected
运行 python run.py -v -m smoke,结果:
======================================================== test session starts ========================================================
platform linux -- Python 3.12.3, pytest-9.0.2, pluggy-1.6.0
configfile: pytest.toml
collected 3 items / 2 deselected / 1 selected
cases/test_a.py::test_eval[6*7-42] PASSED [100%]
================================================== 1 passed, 2 deselected in 0.01s ==================================================
参数化中使用 Fixture
@pytest.mark.parametrize 的 indirect(默认为 False ) 参数,其作用是将参数化的参数传递给同名的 fixture,由 fixture 处理后再传递给测试函数。
参数 ‘indirect = True’ 时,将参数化的参数传递给同名的 Fixture 函数:
import pytest
@pytest.fixture()
def one_param_fixture(request):
"""
通过 request.param 获取参数值
"""
return request.param*2
@pytest.fixture()
def one_param_fixture2(request):
"""
通过 request.param 获取参数值
"""
return request.param*2
@pytest.mark.parametrize("one_param_fixture,one_param_fixture2", [(2, 3)], indirect=True)
def test_one_param_fixture(one_param_fixture, one_param_fixture2):
assert (one_param_fixture, one_param_fixture2) == (2, 3)
运行结果:
======================================================== test session starts ========================================================
platform linux -- Python 3.12.3, pytest-9.0.2, pluggy-1.6.0
configfile: pytest.toml
collected 1 item
cases/test_a.py::test_one_param_fixture[2-3] FAILED [100%]
============================================================= FAILURES ==============================================================
____________________________________________________ test_one_param_fixture[2-3] ____________________________________________________
...
====================================================== short test summary info ======================================================
FAILED cases/test_a.py::test_one_param_fixture[2-3] - AssertionError: assert (4, 6) == (2, 3)
========================================================= 1 failed in 0.04s =========================================================
可以看到参数化参数传递到同名的 Fixture 函数,又传递给测试函数。
参数 ‘indirect = False’(默认) 时,只将参数化的参数传递给测试函数:
import pytest
@pytest.fixture()
def one_param_fixture(request):
"""
通过 request.param 获取参数值
"""
return request.param*2
@pytest.fixture()
def one_param_fixture2(request):
"""
通过 request.param 获取参数值
"""
return request.param*2
@pytest.mark.parametrize("one_param_fixture,one_param_fixture2", [(2, 3)])
def test_one_param_fixture(one_param_fixture, one_param_fixture2):
assert (one_param_fixture, one_param_fixture2) == (2, 3)
运行结果:
======================================================== test session starts ========================================================
platform linux -- Python 3.12.3, pytest-9.0.2, pluggy-1.6.0
configfile: pytest.toml
collected 1 item
cases/test_a.py::test_one_param_fixture[2-3] PASSED [100%]
========================================================= 1 passed in 0.01s =========================================================
可以看到参数化参数只传递到测试函数。
参数 indirect 为列表时,参数化参数传递给列表中的 Fixture 函数,其余只传递给测试函数:
import pytest
@pytest.fixture()
def one_param_fixture(request):
"""
通过 request.param 获取参数值
"""
return request.param*2
@pytest.fixture()
def one_param_fixture2(request):
"""
通过 request.param 获取参数值
"""
return request.param*2
@pytest.mark.parametrize("one_param_fixture,one_param_fixture2", [(2, 3)], indirect= ["one_param_fixture2"])
def test_one_param_fixture(one_param_fixture, one_param_fixture2):
assert (one_param_fixture, one_param_fixture2) == (2, 3)
运行结果:
======================================================== test session starts ========================================================
platform linux -- Python 3.12.3, pytest-9.0.2, pluggy-1.6.0
configfile: pytest.toml
collected 1 item
cases/test_a.py::test_one_param_fixture[2-3] FAILED [100%]
============================================================= FAILURES ==============================================================
____________________________________________________ test_one_param_fixture[2-3] ____________________________________________________
...
====================================================== short test summary info ======================================================
FAILED cases/test_a.py::test_one_param_fixture[2-3] - AssertionError: assert (2, 6) == (2, 3)
========================================================= 1 failed in 0.04s =========================================================
可以看到参数化参数,只传递到列表中的 Fixture 函数,其余传递给测试函数。
THEEND
© 转载需要保留原始链接,未经明确许可,禁止商业使用。CC BY-NC-ND 4.0