如何让Python unittest仅在测试失败时输出日志消息
问题根因
unittest --buffer的核心逻辑是测试执行前将sys.stdout/sys.stderr替换为内存缓冲区,测试通过则丢弃缓冲区内容,失败才将缓冲区内容打印到终端。
你在调用logging.basicConfig时指定了stream=sys.stdout,此时logging会将当前的原始stdout对象永久绑定到默认的日志Handler上,后续unittest替换sys.stdout的操作不会同步到logging的Handler配置,因此日志输出直接绕过了buffer机制,无论测试是否通过都会直接打印。
最简解决方案
我们可以通过一个代理流类,让日志始终输出到当前生效的sys.stdout,即可让logging的输出被unittest的buffer正常捕获:
import logging import unittest import sys logger = logging.getLogger('abc') # 自定义代理流,每次写入都指向当前的sys.stdout class DelegatedStdout: def write(self, buf): sys.stdout.write(buf) def flush(self): sys.stdout.flush() logging.basicConfig( format = '%(asctime)s %(module)s %(levelname)s: %(message)s', level = logging.INFO, stream = DelegatedStdout() # 替换原有的sys.stdout参数 ) class TestABC(unittest.TestCase): def test_abc_pass(self): logger.info('log abc in pass') print('print abc in pass') self.assertTrue(True) def test_abc_fail(self): logger.info('log abc in fail') print('print abc in fail') self.assertTrue(False)
修改后再次执行python -m unittest --buffer,成功用例的日志和print输出都会被抑制,仅失败用例的日志和print会随错误信息一同输出,符合预期要求。
可选方案:自定义测试基类实现日志缓存
如果不想修改全局logging配置,也可以通过重写unittest测试类的生命周期方法,自行实现日志的缓存和丢弃逻辑:
- 在
setUp方法中为logger添加一个内存缓存Handler - 重写
tearDown方法,判断当前测试用例是否执行失败,失败则将缓存的日志输出,成功则清空缓存
这种方案无需依赖--buffer参数,也能实现仅失败用例输出日志的效果。
内容的提问来源于stack exchange,提问作者Satyen A.
相关产品推荐
相关产品推荐

