为了进行单元测试,我想知道特定记录器(logging.Logger
实例)的级别。目标是在测试环境中临时修改记录器以记录所有级别,然后将其设置回以前的级别。我找不到找到上一级的安全方法。
此对象有getEffectiveLevel()
,如果已设置,则返回级别,或者在树上返回它遇到的第一个非零级别。这种方法对我没有好处,因为我不知道返回的值是父级还是实际的记录器。
我找不到另一种方法。
答案 0 :(得分:0)
因此,答案是检查logger.level
属性(未记录),保留其值的副本,最后将其还原。
完整的代码,以显示如何在上下文管理器中使用它来计数已记录的消息数:
class TestLogging(logging.Handler):
"""Context checking the number of logging messages from a specified Logger.
It disables propagation of logging message while running.
This is meant to be used as a with statement, for example:
>>> with TestLogging(logger, error=2, warning=0):
>>> pass # Run tests here expecting 2 ERROR and no WARNING from logger
...
:param logger: Name or instance of the logger to test.
(Default: root logger)
:type logger: str or :class:`logging.Logger`
:param int critical: Expected number of CRITICAL messages.
Default: Do not check.
:param int error: Expected number of ERROR messages.
Default: Do not check.
:param int warning: Expected number of WARNING messages.
Default: Do not check.
:param int info: Expected number of INFO messages.
Default: Do not check.
:param int debug: Expected number of DEBUG messages.
Default: Do not check.
:param int notset: Expected number of NOTSET messages.
Default: Do not check.
:raises RuntimeError: If the message counts are the expected ones.
"""
def __init__(self, logger=None, critical=None, error=None,
warning=None, info=None, debug=None, notset=None):
if logger is None:
logger = logging.getLogger()
elif not isinstance(logger, logging.Logger):
logger = logging.getLogger(logger)
self.logger = logger
self.records = []
self.count_by_level = {
logging.CRITICAL: critical,
logging.ERROR: error,
logging.WARNING: warning,
logging.INFO: info,
logging.DEBUG: debug,
logging.NOTSET: notset
}
super(TestLogging, self).__init__()
def __enter__(self):
"""Context (i.e., with) support"""
self.records = [] # Reset recorded LogRecords
self.logger.addHandler(self)
self.logger.propagate = False
# ensure no log message is ignored
self.entry_level = self.logger.level * 1
self.logger.setLevel(logging.DEBUG)
def __exit__(self, exc_type, exc_value, traceback):
"""Context (i.e., with) support"""
self.logger.removeHandler(self)
self.logger.propagate = True
self.logger.setLevel(self.entry_level)
for level, expected_count in self.count_by_level.items():
if expected_count is None:
continue
# Number of records for the specified level_str
count = len([r for r in self.records if r.levelno == level])
if count != expected_count: # That's an error
# Resend record logs through logger as they where masked
# to help debug
for record in self.records:
self.logger.handle(record)
raise RuntimeError(
'Expected %d %s logging messages, got %d' % (
expected_count, logging.getLevelName(level), count))
def emit(self, record):
"""Override :meth:`logging.Handler.emit`"""
self.records.append(record)