【问题标题】:PyTest parameterizing multiple fixturesPyTest 参数化多个夹具
【发布时间】:2020-10-22 01:09:50
【问题描述】:

我正试图以一种很好的方式解决这个问题,但似乎无法让它发挥作用。

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

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 个。

【问题讨论】:

    标签: python-3.x pytest


    【解决方案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 装饰器添加到所有或部分测试的效果相同。

    【讨论】:

    • 好的,我知道需要做什么了。作为后续问题,不使用固定装置。你什么时候使用fixture vs parameterize?
    • 我在答案中添加了评论。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-03
    • 2022-01-21
    • 1970-01-01
    • 2022-12-08
    • 1970-01-01
    • 2015-11-23
    相关资源
    最近更新 更多