如何使用unittest测试日志消息且不打印到屏幕
嘿,这个问题我之前写单元测试的时候也碰到过!要在unittest里验证日志消息又不把它打印到屏幕上,其实Python的logging模块和unittest框架本身就提供了很方便的解决方案,完全不用找什么Logger迭代器~
解决方案:在unittest中捕获并验证日志消息
方法一:使用unittest自带的assertLogs上下文管理器(推荐,Python3.4+可用)
这是官方推荐的方式,专门为单元测试设计,能自动捕获指定Logger的日志,同时不会输出到控制台。
import logging import unittest # 初始化你的Logger logger = logging.getLogger('test') class TestLoggingMessages(unittest.TestCase): def test_warning_is_logged(self): # 上下文管理器指定要监控的Logger名称和日志级别 with self.assertLogs('test', level='WARNING') as log_context: # 触发要测试的日志 logger.warning('this is a warning') # 断言日志消息内容正确 self.assertIn('this is a warning', log_context.output[0]) # 还可以断言日志的级别是否正确 self.assertEqual(log_context.records[0].levelname, 'WARNING') # 甚至可以断言日志的其他属性,比如logger名称 self.assertEqual(log_context.records[0].name, 'test') if __name__ == '__main__': unittest.main()
说明:
assertLogs会临时接管指定Logger的输出,把日志存到内存里log_context.output是格式化后的日志字符串列表log_context.records是LogRecord对象的列表,能获取日志的级别、消息、时间戳、Logger名称等所有细节- 这个方法会自动处理日志级别过滤,不用手动调整全局的
basicConfig
方法二:手动添加内存Handler(兼容Python3.4以下版本)
如果你的项目还在使用较旧的Python版本,可以手动给Logger添加一个指向内存缓冲区的Handler,把日志捕获到内存中再验证。
import logging import unittest from io import StringIO logger = logging.getLogger('test') class TestLoggingLegacy(unittest.TestCase): def setUp(self): # 创建一个StringIO作为内存缓冲区,用来存日志 self.log_buffer = StringIO() # 创建StreamHandler,把输出指向内存缓冲区 self.log_handler = logging.StreamHandler(self.log_buffer) # 设置Handler的日志级别(只捕获WARNING及以上) self.log_handler.setLevel(logging.WARNING) # 可以自定义日志格式,方便后续断言 formatter = logging.Formatter('%(levelname)s: %(message)s') self.log_handler.setFormatter(formatter) # 给Logger添加这个Handler logger.addHandler(self.log_handler) # 确保Logger的级别足够低,能捕获到WARNING logger.setLevel(logging.WARNING) def test_warning_capture(self): # 触发警告日志 logger.warning('this is a warning') # 读取缓冲区里的日志内容 captured_log = self.log_buffer.getvalue() # 验证日志内容 self.assertIn('WARNING: this is a warning', captured_log) def tearDown(self): # 测试结束后移除Handler,避免影响其他测试用例 logger.removeHandler(self.log_handler) if __name__ == '__main__': unittest.main()
说明:
setUp和tearDown方法用来在每个测试用例前后初始化和清理Handler,避免测试污染StringIO相当于内存中的文件,所有日志输出会被写入这里而不是控制台- 注意:测试完成后一定要移除自定义Handler,否则其他测试的日志可能会被错误捕获
为什么你的原代码看不到警告?
你原来的代码里logging.basicConfig(level=logging.ERROR)设置了全局日志级别为ERROR,所以WARNING级别的日志不会被默认的控制台Handler输出;同时你没有添加任何能保存日志记录的Handler,所以日志生成后直接被丢弃了,自然没法查看。
内容的提问来源于stack exchange,提问作者Ray Salemi
相关产品推荐
相关产品推荐

