在 Pytest 中测试具有许多固定装置/场景的单个单元测试用例
Testing a single unit test case with many fixtures / scenarios in Pytest
我有一个代表某种复杂状态的class。该状态可以改变,我有另一个代表 "true" 状态的 class 实例。我写了一个函数,它执行一些差异逻辑并弄清楚如何将当前状态变为真实状态,如果它们不同的话。
我想使用 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 fixtures parametrization,但这种方法的问题是它使用了装饰器,而且很快变得丑陋*,尤其是在有大量参数和大量测试用例的情况下。看来这不是我应该使用固定装置的目的。
干净利落地实现我想要做的事情的最佳方法是什么?
*我说它变得丑陋是因为装饰器有 15 或 20 组参数非常混乱并且在装饰器本身中加入了很多逻辑。
我认为你可以使用 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']
我使用 "bundle" fixture 构造将输入和输出连接在一起。然后测试看起来很干净:
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" 夹具)变得非常大,您可以在其他地方定义它并格式化代码以提高可读性,从数据文件加载它等.
我有一个代表某种复杂状态的class。该状态可以改变,我有另一个代表 "true" 状态的 class 实例。我写了一个函数,它执行一些差异逻辑并弄清楚如何将当前状态变为真实状态,如果它们不同的话。
我想使用 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 fixtures parametrization,但这种方法的问题是它使用了装饰器,而且很快变得丑陋*,尤其是在有大量参数和大量测试用例的情况下。看来这不是我应该使用固定装置的目的。
干净利落地实现我想要做的事情的最佳方法是什么?
*我说它变得丑陋是因为装饰器有 15 或 20 组参数非常混乱并且在装饰器本身中加入了很多逻辑。
我认为你可以使用 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']
我使用 "bundle" fixture 构造将输入和输出连接在一起。然后测试看起来很干净:
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" 夹具)变得非常大,您可以在其他地方定义它并格式化代码以提高可读性,从数据文件加载它等.