9

你怎么能用 Python 编写一个单元测试来测试记录器的输出是否确实是你期望的格式(即通过调用 logging.basicConfig() 来设置)?我正在考虑自定义 StreamHandler 和使用“re”库,但看起来传递给 StreamHandler.emit() 的 LogRecord 不能给我将输出的字符串。

4

2 回答 2

7

从文档(http://packages.python.org/testfixtures/logging.html):

为了解决这个问题,TestFixtures 允许您轻松捕获对 Python 日志框架的调用输出,并确保它们符合预期。根据您编写的测试类型,共有三种不同的技术。

  1. 上下文管理器
  2. 装饰师
  3. 手动使用

示例包含在文档中。缩短版如下。

上下文管理器

>>> import logging
>>> from testfixtures import LogCapture
>>> with LogCapture() as l:
...     logger = logging.getLogger()
...     logger.info('a message')
...     logger.error('an error')

之后,您可以检查日志是否相等:

>>> l.check(
...     ('root', 'INFO', 'a message'),
...     ('root', 'ERROR', 'another error'),
...     )
Traceback (most recent call last):
 ...
AssertionError: Sequence not as expected:

same:
(('root', 'INFO', 'a message'),)

first:
(('root', 'ERROR', 'another error'),)

second:
(('root', 'ERROR', 'an error'),)

装饰师

与上一个类似,但适用于特定功能:

from testfixtures import log_capture

@log_capture()
def test_function(l):
    logger = logging.getLogger()
    logger.info('a message')
    logger.error('an error')

    l.check(
        ('root', 'INFO', 'a message'),
        ('root', 'ERROR', 'an error'),
        )

手动使用

>>> from testfixtures import LogCapture
>>> l = LogCapture()

之后,您还可以“检查”日志:

>>> l.check(('root', 'INFO', 'a message'))
<...>

编辑:要访问特定日志并以自定义方式分析它们,您可以迭代l.records(其中l只是LogCapture's 实例)并访问它们中的每一个的一些属性(例如,msg包含发送到记录器的消息,levelname包含级别的代号,还有很多其他属性)。

于 2012-06-22T23:31:57.753 回答
1

如果您只想使用标准库,此解决方案可能会有所帮助。它基于unittestmock库。

例如,如果您有script.py以下内容。

logger = logging.getLogger(__name__)

def log_something():
    logger.debug("something")

你可以为它写一个看起来像这样的测试。

import unittest

import mock

from script import log_something

@mock.patch("script.logger")
def test_function(mock_log):
    log_something()

    assertTrue(
        "something" in mock_log.debug.call_args_list[0][0][0]
    )

这是使用库中的call_args_listmock

[0][0][0]最后解释一下

  1. call_args_list是一个call对象列表,看起来像这样[call("something")]。所以第一个[0]是返回第一个call对象。

  2. 第二个[0]返回对象的参数元组call。它看起来像这样("something",)

  3. 第三[0]返回logger在我们的例子中给出的第一个参数。所以最后的字符串将是 only "something"

于 2019-02-26T13:55:26.697 回答