Pytest.使用堆叠参数化装饰器时定义预期结果的最佳方式



我有两个类似的测试用例,每个用例都有100多行代码,为测试创建辅助对象,这些行非常相似,事实上,测试设置之间只有2行不同,我不想消除代码重复。我认为多重参数化可能会帮助我完成这项任务。使用多个参数化,我可以将设置组合在一个中,并实际为测试提供更好的条件。Bun当每次组合都会产生不同的结果时,在使用多重参数化的同时,我无法思考指定预期结果的最佳方式是什么?

考虑这个测试用例

@pytest.mark.parametrize('country', ['US', 'DE', 'FR', 'IT'])
@pytest.mark.parametrize('number', ['12345', '54321'])
def test_correct_record_is_selected_for_number(country, number):
# 100 line long setup of different objects.
record = get_record(country, number)
assert record = expected_record

我预计,对于(country, number)get_record函数的不同组合,将返回不同的结果,我认为提供预期结果的唯一方法是在测试本身中重新实现get_record函数逻辑的部分,以便根据提供的countrynumber来确定预期的结果,这对我来说似乎不正确

有没有一种方法可以很好地指定堆叠的parametrize装饰器的预期输出?或者,我最好将设置代码移动到多个不同的固定装置,并将其保留为使用不同设置固定装置的两个单独的测试?

通常我将结果放在一个单独的fixture中,该fixture根据其他参数选择期望值。示例:

expected_records = {'US': {'12345': 'fizz', '54321': 'buzz'}, 'DE': ...}

@pytest.fixture
def expected_record(request):
country = request.node.funcargs['country']
number = request.node.funcargs['number']
return expected_records.get(country, dict()).get(number, None)

@pytest.mark.parametrize('country', ['US', 'DE', 'FR', 'IT'])
@pytest.mark.parametrize('number', ['12345', '54321'])
def test_correct_record_is_selected_for_number(country, number, expected_record):
record = get_record(country, number)
assert record == expected_record

然而,在实践中,数据很少在脚本中进行硬编码,因此expected_record的逻辑通常是数据驱动的,例如:

@pytest.fixture
def expected_record(request):
country = request.node.funcargs['country']
number = request.node.funcargs['number']
file = pathlib.Path(request.config.rootdir, 'data', country).with_suffix('.json') # data/DE.json
data = json.loads(file.read_text())  # {12345: "fizz", 54321: "buzz"}
return data[number]

我不知道有什么好方法,但无论如何,你都必须在某个地方列出不同的预期结果。所以你可以把它们放在测试之外的字典里:

expected_record = {
'US': {
'12345': {...},
'54321': {...},
},
'DE': {
'12345': {...},
'54321': {...},
},
...
}
@pytest.mark.parametrize('country', ['US', 'DE', 'FR', 'IT'])
@pytest.mark.parametrize('number', ['12345', '54321'])
def test_correct_record_is_selected_for_number(country, number):
record = get_record(country, number)
assert record == expected_record[country][number]

最新更新