在 pytest 中使用双参数化将测试标记为 xfail

Eyt*_*Gro 4 python pytest parametrized-testing

我有一个 pytest 测试,可以针对两个不同的数据库测试多个输入。我使用参数化标记两次来做到这一点:

@pytest.mark.parametrize(
    "input_type",
    [
        pytest.param("input_1"),
        pytest.param("input_2"),
    ],
)
@pytest.mark.parametrize(
    "db_type",
    [
        pytest.param("db_type_1"),
        pytest.param("db_type_2"),
    ],
)
Run Code Online (Sandbox Code Playgroud)

我所经历的只是当运行input_1db_type_2例如)测试由于错误而失败但使用不同的数据库传递运行相同的输入时。input_1我只想将和组合标记db_type_2为 xfail,而所有其他组合不应标记为 xfail。我找不到如何做到这一点。

如果标记db_type_2为 xfail:

@pytest.mark.parametrize(
    "db_type",
    [
        pytest.param("db_type_1"),
        pytest.param("db_type_2", marks=pytest.mark.xfail)
    ],
)
Run Code Online (Sandbox Code Playgroud)

所有输入都将失败,这不是我正在寻找的行为。有人可以帮我解决这个问题吗?

hoe*_*ing 5

您无法根据pytest.mark.parametrize/中的完整参数集来标记测试pytest.param,有关其他参数的信息根本不存在。通常,我将测试参数的后处理移到单独的夹具中,然后可以根据完整的测试参数集更改测试。例子:

@pytest.mark.parametrize('x', range(10))
@pytest.mark.parametrize('y', range(20))
def test_spam(x, y):
    assert False
Run Code Online (Sandbox Code Playgroud)

我们总共进行了 200 项测试;假设我们想要xfail测试x=3y=15x=8, y=1。我们添加一个新的固定装置,可以在启动之前xfail_selected_spams访问两者x,并在必要时将标记附加到测试实例:ytest_spamxfail

@pytest.fixture
def xfail_selected_spams(request):
    x = request.getfixturevalue('x')
    y = request.getfixturevalue('y')

    allowed_failures = [
        (3, 15), (8, 1),
    ]
    if (x, y) in allowed_failures:
        request.node.add_marker(pytest.mark.xfail(reason='TODO'))
Run Code Online (Sandbox Code Playgroud)

要注册夹具,请使用pytest.mark.usefixtures

@pytest.mark.parametrize('x', range(10))
@pytest.mark.parametrize('y', range(20))
@pytest.mark.usefixtures('xfail_selected_spams')
def test_spam(x, y):
    assert False
Run Code Online (Sandbox Code Playgroud)

现在运行测试时,我们将得到198 failed, 2 xfailed结果,因为两个选定的测试预计会失败。