在logger.warning呼叫上使单元测试失败

时间:2019-06-21 16:46:03

标签: python-3.x python-unittest

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

3 个答案:

答案 0 :(得分:1)

unittest具有assertLogs上下文管理器,用于捕获日志记录(自Python 3.4开始添加,对于较旧的版本,使用unittest2 backport lib)。用法示例:

spam.py(要测试的代码)

import logging
logging.getLogger(__name__).addHandler(logging.NullHandler())


def eggs():
    logging.warning('hello world')

测试:

import unittest
import spam

class SpamTests(unittest.TestCase):

    def test_eggs(self):
        with self.assertLogs() as ctx:
            spam.eggs()
        # we expect one record to be captured
        self.assertEqual(len(ctx.records), 1)
        record = ctx.records[0]
        # we expect the captured record to have the message 'hello world'
        self.assertEqual(record.message, 'hello world')

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

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

答案 1 :(得分:0)

对于真正的单元测试,您实际上将要模拟对logger.war的调用,使用patch发出警告。然后,您可以使用该模拟程序来断言该函数是通过使用以下方法的补丁来调用,使用某些参数调用还是根本没有调用:assert_drawn_once(),assert_call_once_with()和assert_not_drawn()。 Patching很棒!

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

答案 2 :(得分:0)

什么都没记录,self.assertLogs() contextManager发出一个AssertionError: no logs of level WARNING or higher triggered on root

我们正好相反。

这是我为避免这种情况写的摘录:

import logging
from contextlib import contextmanager

@contextmanager
def assertNoLog(self, level='WARNING'):
    with self.assertLogs(level=level) as cm:
        yield
        logging.error("gotcha ! with 1 log, you cannot fail before I check ;p")
    if cm.output[:-1]:  # let's remove this last log
        for r in cm.records[:-1]:
            print(r)  # print full failing logs for debug
        raise AssertionError("Log with level >= {level} received".format(level=level),
                             cm.output[:-1])

以及在单元测试中:

def test_my_program(self):
    with assert_no_log(self):
        logging.warning('Oh no! an Unexpected warning! This should fail tests!')

返回:

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