【问题标题】:unittest & logging | capture logs sent to StreamHandler(sys.stdout)单元测试和日志|捕获发送到 StreamHandler(sys.stdout) 的日志
【发布时间】:2021-11-21 10:08:11
【问题描述】:

我想捕获发送到 Stream 的日志。

MyCode.py 将日志传递到控制台:2021-09-29 15:06:11,382 - root - ERROR - Started。但是,captured.records 什么也不返回。 (输出中的前 2 行)

来源


问题

  • 为什么captured 什么都不返回?
  • 如何捕获发送到StreamHandler(sys.stdout) 的日志?

MyCode.py:

import logging
import sys

logger = logging.getLogger()
streamHandler = logging.StreamHandler(sys.stdout)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
streamHandler.setFormatter(formatter)
logger.addHandler(streamHandler)
logger.error('Started')

main.py:

import unittest
from unittest import TestCase
import MyCode

class TestExample(TestCase):
    def test_logging(self):
        with self.assertLogs() as captured:
            print('captured.records: ', captured.records)
            self.assertEqual(len(captured.records), 1)
            self.assertTrue("Started" in captured.records[0].getMessage())

if __name__ == '__main__':
    unittest.main()

控制台:

2021-09-29 15:06:11,382 - root - ERROR - Started
captured.records:  []
F
======================================================================
FAIL: test_logging (__main__.TestExample)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "main.py", line 9, in test_logging
    self.assertEqual(len(captured.records), 1)
AssertionError: 0 != 1

----------------------------------------------------------------------
Ran 1 test in 0.001s

FAILED (failures=1)
repl process died unexpectedly: exit status 1

如果还有什么需要补充的,请告诉我。

【问题讨论】:

    标签: python unit-testing logging pytest


    【解决方案1】:

    assertLogs 上下文管理器仅捕获在其上下文中创建的日志消息。您的日志消息是在导入 MyCode 时创建的,这发生在创建日志断言上下文之前。

    如果您将代码放在一个函数中,并在测试中运行该函数,它应该可以工作。

    MyCode.py

    import logging
    import sys
    
    def foo():
        logger = logging.getLogger()
        streamHandler = logging.StreamHandler(sys.stdout)
        formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - (message)s')
        streamHandler.setFormatter(formatter)
        logger.addHandler(streamHandler)
        logger.error('Started')
    

    ma​​in.py

    import unittest
    from unittest import TestCase
    import MyCode
    
    class TestExample(TestCase):
        def test_logging(self):
            with self.assertLogs() as captured:
                MyCode.foo()
                print('captured.records: ', captured.records)
                self.assertEqual(len(captured.records), 1)
                self.assertTrue("Started" in captured.records[0].getMessage())
    
    if __name__ == '__main__':
        unittest.main()
    

    【讨论】:

    • 如果您需要验证是否发生了日志记录,并且该日志记录必须发生在您的测试上下文之外,您可以向记录器添加另一个处理程序,该处理程序只是将日志消息存储在一个列表中。另一种选择是使用logging.FileHandler 并验证文件的内容。
    • Tysm。我将尝试这个解决方案并在这里报告。是的,我需要一个list(要求是在运行时不要有太多文件)。
    • 传奇!打字机。有用。我如何在MyCode.py 中创建一个list,以将logger.error()s 附加到main.py 可以访问?
    • 我会从这个答案stackoverflow.com/a/36408692/15013600 看一下自定义日志处理程序。您只需将该处理程序的一个实例添加到您的记录器,而不是(或除了)streamHandler。另外仅供参考,让您的模块记录到根记录器以外的其他东西通常是个好主意。在大多数情况下,您会希望使用基于模块名称的记录器(例如,在MyCode.py 中,您会使用LOGGER = logging.getLogger(__name__))。然后您需要调整您的 assertLogs 调用以包含记录器的名称:with self.assertLogs(logger=MyCode.__name__)
    猜你喜欢
    • 2013-12-29
    • 2016-05-13
    • 1970-01-01
    • 2010-11-25
    • 2017-05-28
    • 1970-01-01
    • 1970-01-01
    • 2020-12-10
    • 1970-01-01
    相关资源
    最近更新 更多