PyTest参数化多个灯具

时间:2020-10-22 01:09:50

标签: python-3.x pytest

我正在尝试以一种不错的方式解决这个问题,但似乎无法使其正常工作。

假设我要测试以下业务逻辑:

class MyClass:
    def __init__(self, value):
        self.value = value

    def execute(self):
        return self.value

和以下测试用例:

test_cases = [
    {
        'name': "assert True",
        'data': True,
        'expected': False
    }, {
        'name': "assert False",
        'data': False,
        'expected': True
    }
]

然后我想编写以下测试套件:

def idfn(val):
    return val.get('name')

@pytest.fixture(params=test_cases, ids=idfn)
def my_class(request):
    return MyClass(request.param['data'])


@pytest.fixture(params=test_cases, ids=idfn)
def expected(request):
    return request.param['expected']


class Test():
    def test_execute(self, my_class, expected):
        assert my_class.execute() == expected

如何避免pytest进行每种可能的测试用例组合?我只想生成2个测试,因为我有2个测试用例,但是PyTest正在生成4个。

pytest test collection

1 个答案:

答案 0 :(得分:1)

如果要使用多个耦合参数(dataexpected),则只需将它们组合在单个夹具中或在单个parametrize调用中,否则夹具将始终如您所见组合在一起:

@pytest.fixture(params=test_cases, ids=idfn)
def my_class_cases(request):
    return MyClass(request.param['data']), request.param['expected']

class Test:
    def test_execute(self, my_class_cases):
        assert my_class_cases[0].execute() == my_class_cases[1]

或使用字典来提高可读性:

@pytest.fixture(params=test_cases, ids=idfn)
def my_class_cases(request):
    return {'class': MyClass(request.param['data']),
            'expected': request.param['expected']}

class Test:
    def test_execute(self, my_class_cases):
        assert my_class_cases['class'].execute() == my_class_cases['expected']

对于您来说,也可以不使用固定装置而直接使用mark.parametrize

def get_test_params():
    return [(MyClass(case['data']), case['expected']) for case in test_cases]

def getids():
    return [case['name'] for case in test_cases]

class Test:
    @pytest.mark.parametrize("my_class,data", get_test_params(), ids=getids())
    def test_execute(self, my_class, data):
        assert my_class.execute() == data

哪种选择取决于口味。
在这种情况下,使用mark.parametrize可能是更好的选择,因为单独的参数使其更具可读性。如果您想在多个测试中使用参数,并且测试数据的读取范围很广,则夹具可能是更好的选择。
请注意,还可以选择对pytest_generate_tests中的测试进行参数化,其效果与向所有或某些测试中添加mark.parametrize装饰器相同。