在Pytest中使用多个装置/场景测试单个单元测试用例

问题描述 投票:3回答:1

我有一个表示特定复杂状态的类。该状态可以更改,而我有该类的另一个实例,表示“真实”状态。我编写了一个函数,该函数执行一些差异逻辑,并弄清楚了如何将当前状态变为真实状态(如果它们不同)。

我想使用pytest测试该功能。有很多场景可能,但是测试逻辑非常简单,并且可以归结为(伪python代码):

def test_diffing(current_state, prescribed_state):
    properties_to_add = []
    properties_to_delete = []
    properties_to_modify = []
    properties_to_add, properties_to_delete, properties_to_modify = diff_logic(current_state, prescribed_state)

    assert properties_to_add == 1
    assert properties_to_delete == 0
    assert properties_to_modify == 3

断言右侧的数字取决于current_state是什么。我有很多current_state场景。

编写上述具有多个夹具的单个单元测试的最佳方法是什么,以使current_state与assert的期望值一起传递?

我已经看过pytest固定装置的参数化,但是这种方法的问题在于它正在使用装饰器,而且很快就会变得难看*,特别是在有大量参数和大量测试用例的情况下。看来这不是我应该使用的灯具。

实现我正在尝试做的最好的方法是什么?

*我说这很丑,因为装饰器具有15或20组参数非常混乱,并且在装饰器本身中增加了很多逻辑。

python unit-testing pytest fixtures
1个回答
3
投票

我认为您可以使用parametrized fixtures达到所需的水平。

怎么样:

@pytest.fixture(params=[
    {
        'current_state': 'foo',
        'expected': {
            'properties_to_add': 1,
            'properties_to_delete': 2,
            'properties_to_modify': 3,
        },
    },
    ... as many scenarios as you'd like ...
])
def bundle(request):
    return request.param

@pytest.fixture
def current_state(bundle):
    return bundle['current_state']

@pytest.fixture
def expected(bundle):
    return bundle['expected']

我使用“捆绑”夹具构造将输入和输出绑定在一起。然后测试看起来很干净:

def test_diffing(current_state, expected):
    prescribed_state = ...  # I assume this is a constant, you can inject "prescribed_state" in the fixture in the same way as "current_state" and "expected"
    properties_to_add, properties_to_delete, properties_to_modify = diff_logic(current_state, prescribed_state)
    assert expected == {
        'properties_to_add': properties_to_add,
        'properties_to_delete': properties_to_delete,
        'properties_to_modify': properties_to_modify,
    }

然后,如果“ params”数据结构(用于“ bundle”灯具)非常大,则可以在其他地方定义它并设置代码格式以提高可读性,并从数据文件中加载它,等等。

© www.soinside.com 2019 - 2024. All rights reserved.