Skip to main content
 首页 » 编程设计

python之为什么单元测试中的 python 记录器在调用 setLevel 后不起作用

2025年01月19日21小虾米

我的 unittest 测试用例中有以下代码:

class StatsdLogHandler(logging.Handler): 
    def emit(self, record): 
        log_entry = self.format(record) 
        statsd_client.incr(log_entry) 
 
def setup_statsd_logging(logger, level=logging.WARNING): 
    # set up statsd counts for logging 
    statsd_format = "pegasus.logger.%(levelname)s.%(name)s" 
    formatter = logging.Formatter(statsd_format) 
    statsd_handler = StatsdLogHandler() 
    statsd_handler.setFormatter(formatter) 
    statsd_handler.setLevel(level) 
    logger.addHandler(statsd_handler) 
 
class TestLogging(unittest.TestCase): 
    @mock.patch('.statsd_client') 
    def test_logging_to_statsd(self, statsd_mock): 
        """Make sure log calls go to statsd""" 
        root_logger = logging.getLogger() 
        setup_statsd_logging(root_logger) 
        root_logger.setLevel(logging.DEBUG) 
        root_logger.warning('warning') 
        statsd_mock.incr.assert_called_with('pegasus.logger.WARNING.root') 

但是,当我运行 TestLogging 测试用例时,我得到

AssertionError: Expected call: incr(u'pegasus.logger.WARNING.root')

Not called

我希望这次电话会成功。为什么会这样?

请您参考如下方法:

当我调试这个行为时,我发现 root_logger.manager.disable 被设置为 30 的值,这意味着所有级别为 WARNING 或更低的日志记录没有被打印出来。

日志记录 Manager 对象没有记录在任何我可以轻松找到的地方,但它是描述和存储所有记录器(包括根记录器)的对象。它在代码中定义 here .我发现测试用例中的其他地方调用了 logging.disable(logging.WARNING)。这会将 root_logger.manager.disable 的值设置为 30。管理器禁用级别胜过记录器的有效级别(参见 this code)。

通过在测试用例的开头添加行 logging.disable(logging.NOTSET) 到我的测试用例,我确保日志管理器 disable 属性是设置为默认值 0,这导致我的测试用例通过。