任何级别的日志记录都可以让assertLogs 通过

Tro*_*els 6 python-3.x python-unittest python-logging

我正在尝试测试单元测试中是否记录了警告。看来以下测试应该失败:

import logging
import unittest

LOG_FORMAT = '%(levelname)-10s %(asctime)s: %(message)s'


def set_up_logger(app_name, level=logging.INFO, file="test.log"):
    formatter = logging.Formatter(LOG_FORMAT)
    log = logging.getLogger(app_name)
    # The next line lets the test pass
    log.setLevel(level)
    return log

logger = set_up_logger(__name__)

class TestLogging(unittest.TestCase):
    def test_logging(self):
        with self.assertLogs(level=logging.WARNING):
            logger.info('foo')
Run Code Online (Sandbox Code Playgroud)

然而,它通过了 python 3.8.5。

如果我删除该log.setLevel(level)行,测试就会失败,正如预期的那样。如果我将该logger.info行替换为pass,那么测试也会按预期失败。

为什么在记录器上设置级别会让测试错误地通过?

MrB*_*men 2

我不完全确定这种行为是否是想要的,因为它有点出乎意料。要修复测试,您必须通过记录器:

class TestLogging(unittest.TestCase):
    def test_logging(self):
        with self.assertLogs(logger, level=logging.WARNING):
            logger.info('foo')
Run Code Online (Sandbox Code Playgroud)

它以这种方式工作的原因是,在assertLogs上下文管理器中,传递的记录器的日志级别暂时设置为传递的级别,如果退出时没有发生日志记录,则测试将失败。

如果传递记录器,则会使用根记录器。如果您没有在记录器上设置级别,它将使用根记录器的级别,该级别在调用期间由上下文管理器设置WARNING- 因此不会记录任何内容,并且测试会按预期失败。

如果您确实设置了日志级别,则无论根记录器级别如何,都将使用该日志级别,因此将完成日志记录并且测试通过(这也不是我所期望的)。

更新:
现在有一个Python 问题描述了该问题,现已在 master 和 Python 3.10 中修复