Python 3.x 使unittests在logger.warning调用上失败

Python 3.x 使unittests在logger.warning调用上失败,python-3.x,python-unittest,Python 3.x,Python Unittest,如果我看到任何写入记录器的警告,我希望Pythonunittest测试失败。如何捕获记录器消息并使测试失败?对于真正的单元测试,您实际上需要使用补丁模拟对记录器的调用。警告。然后,您可以使用该模拟来断言是否调用了该函数,是否使用某些参数调用了该函数,或者是否使用带有以下方法的修补程序调用了该函数:assert_called_once()、assert_called_once_with()和assert_not_called()。太棒了 from unittest import TestCase

如果我看到任何写入记录器的警告,我希望Python
unittest
测试失败。如何捕获记录器消息并使测试失败?

对于真正的单元测试,您实际上需要使用补丁模拟对记录器的调用。警告。然后,您可以使用该模拟来断言是否调用了该函数,是否使用某些参数调用了该函数,或者是否使用带有以下方法的修补程序调用了该函数:assert_called_once()、assert_called_once_with()和assert_not_called()。太棒了

from unittest import TestCase
from unittest.mock import patch
from logging import warning


def simple_function(value):

    if value == 5:
        pass
    else:
        warning(msg='msg')


class TestSimpleFunction(TestCase):

    @patch('test_stack_overflow.warning')
    def test_simple_function_wrong_value(self, log_warning_call):
        simple_function('5')
        log_warning_call.assert_called_once()
        log_warning_call.assert_called_once_with(msg='msg')

    @patch('test_stack_overflow.warning')
    def test_simple_function_right_value(self, log_warning_call):
        simple_function(5)
        log_warning_call.assert_not_called()
unittest
具有用于捕获日志记录的上下文管理器(从Python 3.4开始添加,对于较旧版本,使用backport lib)。用法示例:

spam.py
(待测试代码)

测试:

如果您想在任何具有警告级别的记录上测试失败,您可以检查捕获的记录,按级别过滤:

self.assertFalse([r for r in ctx.records if r.levelno == logging.WARNING])

当未记录任何内容时,
self.assertLogs()
contextManager会发出一个
AssertionError:root上不会触发级别为警告或更高的日志

我们想要的恰恰相反

以下是我为避免这种情况而编写的代码片段:

导入日志
从contextlib导入contextmanager
@上下文管理器
def assertNoLog(自我,级别='WARNING'):
使用self.assertLogs(级别=级别)作为cm:
产量
logging.error(“明白了!使用1个日志,在我检查之前,您不能失败;p”)
如果cm.output[:-1]:#让我们删除最后一个日志
对于厘米记录中的r[:-1]:
打印(r)#打印完整的故障日志以进行调试
raise AssertionError(“接收到级别>={level}的日志”。格式(level=level),
厘米输出[:-1])
在单元测试中:

def test_my_程序(self):
使用assert\u no\u日志(self):
logging.warning('哦,不!意外警告!这应该会导致测试失败!')
返回:

AssertionError: ('Log with level >= WARNING received', 
    ['WARNING:my.module:Oh no! an Unexpected warning! This should fail tests!'])

我做了一个更改,在多个目录中的100个测试中引入了几个警告。我不希望运行所有的测试,而是希望立即停止测试,以便修复警告。这在您的问题中并不清楚。因此,您不想编写新的测试,而是想让遇到任何警告记录的现有测试失败?
self.assertFalse([r for r in ctx.records if r.levelno == logging.WARNING])
AssertionError: ('Log with level >= WARNING received', 
    ['WARNING:my.module:Oh no! an Unexpected warning! This should fail tests!'])