【问题标题】:How to use pytest to assert NO Warning is raised如何使用 pytest 断言没有引发警告
【发布时间】:2018-01-22 03:10:03
【问题描述】:

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

pytest documentation about warnings 中找不到任何明确的答案。

我试过这个,我想None 可能意味着“什么都没有”:

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')

【问题讨论】:

    标签: python python-3.x unit-testing warnings pytest


    【解决方案1】:

    对于 pytest >= 7.0(截至撰写本文时尚未发布):

    使用新的专用上下文管理器:

    with pytest.does_not_warn():
        ...
    

    我会在它实施和 pytest 7.0 发布时更新这篇文章。

    注意:下面的 pytest

    pytest

    然而它并没有计划这样使用,它可以“记录”任何可能引发的警告,并使用它来添加另一个断言以确保引发的警告数量为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') 让测试失败。

    更正式的方式是使用这个(没有 pytest):

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

    虽然它可能不适用于所有情况(动态检查:请参阅this post)。

    【讨论】:

    • 甚至更漂亮:assert not record.list.
    • 或更短:assert not record(见usage example
    • 这不允许您过滤记录。例如,pytest.warns(FutureWarning): pass 失败,因为没有抛出 FutureWarning
    • 仅供参考:pytest.warns(None) 在 pytest 7.0.0 中已弃用。
    【解决方案2】:

    如果您有正在测试其他功能的测试,但您还想断言没有引发任何警告,您可以使用装饰器。这是我根据 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 MyTestClass(TestCase)
    
      @no_warnings
      def test_something(self):
    
          # My important test
          self.assertTrue(True)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-06-13
      • 1970-01-01
      • 2021-08-25
      • 2021-11-25
      • 2013-12-15
      • 2020-05-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多