【问题标题】:Testing a single unit test case with many fixtures / scenarios in Pytest在 Pytest 中使用许多夹具/场景测试单个单元测试用例
【发布时间】:2017-07-11 19:46:35
【问题描述】:

我有一个代表某种复杂状态的类。该状态可以更改,并且我有该类的另一个实例,它表示“真实”状态。我编写了一个函数,它执行一些不同的逻辑,并计算出如何将当前状态变为真实状态,如果它们不同的话。

我想使用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 与断言的预期值一起传递?

我查看了 pytest 固定装置参数化,但这种方法的问题在于它使用了装饰器并且很快就会变得丑陋*,尤其是在有大量参数和大量测试用例的情况下。看来这不是我应该使用固定装置的目的。

什么是实现我想要干净利落的最佳方式?

*我是说它变得丑陋了,因为装饰器有 15 或 20 组参数非常混乱,并且在装饰器本身中加入了很多逻辑。

【问题讨论】:

  • 如果我的理解是正确的,fixture 更多的是为了测试之间的共性,而不是为了改变输入。在您的情况下,如果您要测试 15-20 个独特的场景,最好编写 15-20 个单元测试。
  • 这是有道理的。但是,避免将相同的确切逻辑重复 15-20 次的最佳方法是什么?唯一的区别是 current_state 对象及其预期。

标签: python unit-testing pytest fixtures


【解决方案1】:

我认为你可以使用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”夹具)变得非常大,您可以在其他地方定义它并格式化代码以提高可读性,从数据文件中加载它等等。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-27
    • 2016-10-21
    • 2011-03-16
    • 2010-10-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多