pytest.mark.parametrize似乎只能xfail预期的异常

时间:2018-10-14 22:45:49

标签: exception-handling pytest

参数化引发预期异常的测试时,我一直在使用以下形式:

import pytest

class SomeException(Exception):
    pass

class AnotherException(Exception):
    pass

@pytest.mark.parametrize(
    'error',
    [None,
     pytest.mark.raises(SomeException('the message'),
                        exception=SomeException),
     pytest.mark.raises(AnotherException('the message'),
                        exception=AnotherException),
     pytest.mark.raises(Exception('the message'),
                        exception=Exception),
     ])
def test_mark_raises(error):
    if error:
        raise error

请注意,我已经安装了pytest-raises软件包。好的,这可行,但是最近我注意到它发出了弃用警告:

RemovedInPytest4Warning: Applying marks directly to parameters is deprecated, please use pytest.param(..., marks=...) instead.

好的,很好。我们将更新参数列表。但这是有问题的。 pytest.param有一个'marks ='参数,但是传入pytest.mark.raises无效。我发现在pytest.param中使用异常处理的唯一方法(实际上似乎完全有效)是:

import pytest

class SomeException(Exception):
    pass

class AnotherException(Exception):
    pass

@pytest.mark.parametrize(
    'error',
    [None,
     pytest.param(SomeException('the message'),
                  marks=pytest.mark.xfail(exception=SomeException)),
     pytest.param(AnotherException('the message'),
                  marks=pytest.mark.xfail(exception=AnotherException)),
     pytest.param(Exception('the message'),
                  marks=pytest.mark.xfail(exception=Exception)),
     ])
def test_mark_raises(error):
    if error:
        raise error

好的,所以这似乎确实可行。但是没有通过测试,而是对它们进行了失败。

我不喜欢这样。如果我期望考试能提高 特定的例外,实际上确实引发了例外, 那么我认为测试已经通过,而不是“ xfailed”。

如果我要检查一堆pytest结果(在某些情况下为1500+), 在视觉上,确定哪些测试失败是更多的工作 因为他们期望某种失败条件,以及哪些 正在执行xfailing,因为尚未实施(或其他一些原因) 这表明我们需要修复某些问题。

我不喜欢收到一堆警告,但我还希望测试能正确显示它们已通过。有没有人知道在预期的异常行为下可以与pytest.param一起使用的正确构造?

2 个答案:

答案 0 :(得分:0)

如果要禁用输出中的警告,可以使用--disable-warnings标志。

当您不希望测试失败时,您正在使用xfail引发异常。您应该使用pytest.raises引发异常-link。如果要使用标记引发异常,则应使用自定义标记并编写自己的测试收集器。 conftest.py的示例:

import pytest

def pytest_runtest_setup(item):
    envmarker = item.get_marker("passwithex")
    if envmarker is not None:
        pytest.raises(ErrorName)

测试代码:

import pytest

class SomeException(Exception):
    pass

class AnotherException(Exception):
    pass

@pytest.mark.parametrize(
    'error',
    [None,
     pytest.param(SomeException('the message'),
                  marks=pytest.mark.passwithex),
     pytest.param(AnotherException('the message'),
                  marks=pytest.mark.xfail(exception=AnotherException)),
     pytest.param(Exception('the message'),
                  marks=pytest.mark.xfail(exception=Exception)),
     ])
def test_mark_raises(error):
    if error:
        raise error

答案 1 :(得分:0)

我不确定是回答我自己的问题还是只是更新问题。由于答案有点冗长,因此我选择将其放在此处。

pytest-raises版本0.10现在支持我正在寻找的行为。现在,您可以通过以下方式设置异常参数:

import pytest

class SomeException(Exception):
    pass

@pytest.mark.parametrize(
    'error',
    [None,
     pytest.param(SomeException('the message'),
                  marks=pytest.mark.raises(exception=SomeException)),
     ])
def test_mark_raises(error):
    if error:
        raise error

这比以前接受的将标记直接放入参数列表中的做法更为冗长,但是它可以按预期工作,并且弃用警告消失了。