如何使用 pytest 断言不引发警告

How to use pytest to assert NO Warning is raised

我想确保在一个断言中根本没有警告

无法在 pytest documentation about warnings 中找到任何明确的答案。

我试过了,我想 None 可能意味着 "nothing":

def test_AttrStr_parse_warnings():
    """Check _AttrStr.parse() raises proper warnings in proper cases."""
    with pytest.warns(None):
        _AttrStr('').parse()

但是这个断言也总是正确的,例如,测试不会失败,即使实际上引发了警告:

def test_AttrStr_parse_warnings():
    """Check _AttrStr.parse() raises proper warnings in proper cases."""
    with pytest.warns(None):
        _AttrStr('').parse()
        warnings.warn('any message')

对于 pytest >= 7.0

The doc 现在明确提到这种情况应该以这种方式解决(没有 pytest):

with warnings.catch_warnings():
    warnings.simplefilter("error")
    ...

虽然这可能无法完全解决某些情况(动态检查:参见 this post)。

下面为 pytest < 7.0 建议的解决方案现在引发了 DeprecationWarning。感谢@Warren-Weckesser 在评论中指出这一点!

pytest < 7.0 的可能解决方案

然而它并没有计划像这样使用,它可以“记录”任何可能引发的警告,并使用它来添加另一个断言以确保引发警告的数量是 0:

def test_AttrStr_parse_warnings():
    """Check parse() raises proper warnings in proper cases."""
    with pytest.warns(None) as record:
        _AttrStr('').parse()
    assert len(record) == 0

为确保它有效:在第二个断言中添加 warnings.warn('any message') 让测试失败。

如果您有测试其他功能的测试,但您还想断言没有发出警告,您可以使用装饰器。这是我根据 zezollo

之前接受的答案写的
def no_warnings(func):

    def wrapper_no_warnings(*args, **kwargs):

        with pytest.warns(None) as warnings:
            func(*args, **kwargs)

        if len(warnings) > 0:
            raise AssertionError(
                "Warnings were raised: " + ", ".join([str(w) for w in warnings])
            )

    return wrapper_no_warnings

然后您可以修饰测试 class 函数以添加此断言。

class MyTestClass(TestCase)

  @no_warnings
  def test_something(self):

      # My important test
      self.assertTrue(True)