我可以创建一个 pytest.fixture 的 returns 参数组合吗?

Can I create a pytest.fixture that returns combinations of arguments?

正在测试的算法的输入是一个字符串列表(预先知道)以及相关年份,例如以下所有都是有效输入:

['A_2018', 'B_2019', 'C_2018']
[]
['A_2018']

我有以下简单的年份固定装置:

@pytest.fixture(params=range(2018, 2025))
def year(request):
    return request.param

如果我为每个有效字符串创建单独的装置:

@pytest.fixture(params=['A', ''])
def A(request, year):
    return request.param, year

@pytest.fixture(params=['B', ''])
def B(request, year):
    return request.param, year

等并在以下测试中使用它们:

def test_foo(A, B):
    args = []
    if A[0]:
        args.append('%s_%d' % A)
    if B[0]:
        args.append('%s_%d' % B)
    assert old_algorithm(args) == new_algorithm(args)

我明白了

['A_2018', 'B_2018']
['A_2019', 'B_2019']
['A_2020', 'B_2020']

等两个参数的年份始终相同。

有没有办法创建所有组合?

是否需要生成组合的夹具?因为否则,为每个测试输入 arg 单独应用 pytest.mark.parametrize 就可以很好地生成输入 args 组合。在下面的示例中,两个固定装置 AB 分别进行参数化,总共生成 (2025 - 2018)**2 测试:

@pytest.fixture
def A(request):
    return 'A', request.param


@pytest.fixture
def B(request):
    return 'B', request.param


@pytest.mark.parametrize('A', range(2018, 2025), indirect=True, ids=lambda year: 'A({})'.format(year))
@pytest.mark.parametrize('B', range(2018, 2025), indirect=True, ids=lambda year: 'B({})'.format(year))
def test_foo(A, B):
    assert A[0] == 'A' and B[0] == 'B'

结果,生成了 49 个测试:

$ pytest --collect-only | grep collected
collected 49 items