@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 ======================================================================
collected 3 items                                                                                                                                               

Config::test_math[3-3] PASSED                                                                                                                             [ 33%] 
Config::test_math[4-4] PASSED                                                                                                                             [ 66%] 
Config::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 ======================================================================
collected 4 items                                                                                                                                                

Config::TestClass::test_simple_case[1-2] PASSED                                                                                                           [ 25%] 
Config::TestClass::test_simple_case[3-4] PASSED                                                                                                           [ 50%] 
Config::TestClass::test_weird_simple_case[1-2] PASSED                                                                                                     [ 75%] 
Config::TestClass::test_weird_simple_case[3-4] PASSED                                                                                                     [100%] 

====================================================================== 4 passed in 0.01s =======================================================================  

参数化模块中测试用例

分配给 pytestmark 全局变量,还可以参数化模块中的所有测试:

import pytest

pytestmark = pytest.mark.parametrize("n,expected", [(1, 2), (2, 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

def test_one(n, expected):
    assert n+n == expected


def test_two(n, expected):
    assert n+n == expected

运行结果:

===================================================================== test session starts ======================================================================
collected 8 items                                                                                                                                                

Config::TestClass::test_simple_case[1-2] PASSED                                                                                                           [ 12%] 
Config::TestClass::test_simple_case[2-4] FAILED                                                                                                           [ 25%]
Config::TestClass::test_weird_simple_case[1-2] PASSED                                                                                                     [ 37%] 
Config::TestClass::test_weird_simple_case[2-4] FAILED                                                                                                     [ 50%] 
Config::test_one[1-2] PASSED                                                                                                                              [ 62%] 
Config::test_one[2-4] PASSED                                                                                                                              [ 75%] 
Config::test_two[1-2] PASSED                                                                                                                              [ 87%] 
Config::test_two[2-4] PASSED                                                                                                                              [100%] 

=================================================================== short test summary info ==================================================================== 
FAILED Config::TestClass::test_simple_case[2-4] - assert (2 + 1) == 4
FAILED Config::TestClass::test_weird_simple_case[2-4] - assert ((2 * 1) + 1) == 4
================================================================= 2 failed, 6 passed in 0.02s ================================================================== 

组合参数化

还可以堆叠 parametrize装饰器,获取多个参数的所有组合:


import pytest


@pytest.mark.parametrize("x", [0, 1])
@pytest.mark.parametrize("y", [2, 3])
def test_foo(x, y):
    pass

运行结果:

===================================================================== test session starts ======================================================================
collected 4 items                                                                                                                                               

Config::test_foo[2-0] PASSED                                                                                                                              [ 25%]
Config::test_foo[2-1] PASSED                                                                                                                              [ 50%] 
Config::test_foo[3-0] PASSED                                                                                                                              [ 75%] 
Config::test_foo[3-1] PASSED                                                                                                                              [100%] 

====================================================================== 4 passed in 0.02s ======================================================================= 

会按照 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

运行 pytest -m user,结果:

===================================================================== test session starts ======================================================================
collected 3 items / 2 deselected / 1 selected                                                                                                                    

Config::test_eval[6*7-42] PASSED                                                                                                                          [100%] 

=============================================================== 1 passed, 2 deselected in 0.01s ================================================================  

参数化中使用 Fixture

@pytest.mark.parametrize 的 indirect(默认为 False ) 参数,当 indirect 不为 False 时,允许将参数化测试中的某些参数传递给fixture,而不是直接作为测试函数的参数。

  1. 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*3

@pytest.mark.parametrize("one_param_fixture,one_param_fixture2", [(2, 3), (4, 5)], indirect= True)
def test_one_param_fixture(one_param_fixture, one_param_fixture2):
    assert False, (one_param_fixture, one_param_fixture2)

运行结果:

===================================================================== test session starts ======================================================================
configfile: pytest.ini
plugins: allure-pytest-2.15.0
collected 2 items                                                                                                                                               

tests\aaaaa.py FF                                                                                                                                         [100%]

=========================================================================== FAILURES ===========================================================================
_________________________________________________________________ test_one_param_fixture[2-3] __________________________________________________________________

one_param_fixture = 4, one_param_fixture2 = 9

    @pytest.mark.parametrize("one_param_fixture,one_param_fixture2", [(2, 3), (4, 5)], indirect= True)
    def test_one_param_fixture(one_param_fixture, one_param_fixture2):
>       assert False, (one_param_fixture, one_param_fixture2)
E       AssertionError: (4, 9)
E       assert False

tests\aaaaa.py:38: AssertionError
_________________________________________________________________ test_one_param_fixture[4-5] __________________________________________________________________

one_param_fixture = 8, one_param_fixture2 = 15

    @pytest.mark.parametrize("one_param_fixture,one_param_fixture2", [(2, 3), (4, 5)], indirect= True)
    def test_one_param_fixture(one_param_fixture, one_param_fixture2):
>       assert False, (one_param_fixture, one_param_fixture2)
E       AssertionError: (8, 15)
E       assert False

tests\aaaaa.py:38: AssertionError
=================================================================== short test summary info ====================================================================
FAILED tests/aaaaa.py::test_one_param_fixture[2-3] - AssertionError: (4, 9)
FAILED tests/aaaaa.py::test_one_param_fixture[4-5] - AssertionError: (8, 15)
====================================================================== 2 failed in 0.12s =======================================================================
  1. 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*3

@pytest.mark.parametrize("one_param_fixture,one_param_fixture2", [(2, 3), (4, 5)], indirect= ["one_param_fixture2"])
def test_one_param_fixture(one_param_fixture, one_param_fixture2):
    assert False, (one_param_fixture, one_param_fixture2)

运行结果:

===================================================================== test session starts ======================================================================
configfile: pytest.ini
plugins: allure-pytest-2.15.0
collected 2 items                                                                                                                                               

tests\aaaaa.py FF                                                                                                                                         [100%]

=========================================================================== FAILURES ===========================================================================
_________________________________________________________________ test_one_param_fixture[2-3] __________________________________________________________________

one_param_fixture = 2, one_param_fixture2 = 9

    @pytest.mark.parametrize("one_param_fixture,one_param_fixture2", [(2, 3), (4, 5)], indirect= ["one_param_fixture2"])
    def test_one_param_fixture(one_param_fixture, one_param_fixture2):
>       assert False, (one_param_fixture, one_param_fixture2)
E       AssertionError: (2, 9)
E       assert False

tests\aaaaa.py:38: AssertionError
_________________________________________________________________ test_one_param_fixture[4-5] __________________________________________________________________

one_param_fixture = 4, one_param_fixture2 = 15

    @pytest.mark.parametrize("one_param_fixture,one_param_fixture2", [(2, 3), (4, 5)], indirect= ["one_param_fixture2"])
    def test_one_param_fixture(one_param_fixture, one_param_fixture2):
>       assert False, (one_param_fixture, one_param_fixture2)
E       AssertionError: (4, 15)
E       assert False

tests\aaaaa.py:38: AssertionError
=================================================================== short test summary info ====================================================================
FAILED tests/aaaaa.py::test_one_param_fixture[2-3] - AssertionError: (2, 9)
FAILED tests/aaaaa.py::test_one_param_fixture[4-5] - AssertionError: (4, 15)
====================================================================== 2 failed in 0.12s =======================================================================

THEEND



© 转载需要保留原始链接,未经明确许可,禁止商业使用。CC BY-NC-ND 4.0