如何在Python中将logging模块与unittest模块结合使用?

8 投票
1 回答
2062 浏览
提问于 2025-04-16 01:55

我想用Python的日志模块来记录unittest的所有输出,这样我就可以把它整合进我正在写的测试框架里。我的目标是运行测试时能有两种输出,一种是简单的输出,告诉我测试步骤是什么,另一种是更详细的调试输出,这样当出现问题时,我们能获取尽可能多的信息。这些输出会被放到两个文件里,一个是我可以发给别人的,另一个是留着以防失败。我注意到TextTestRunner可以使用一个流,这个流能和日志模块一起用吗?我打算使用一些Python 2.7的新特性。

1 个回答

1

你可以这样做,但我不确定这是不是最好的方法。

如果你选择这种方法,你需要:

  1. 创建一个内存中的流,这样就可以被 TextTestRunner 使用。这里 io.StringIO 是个不错的选择,但它只支持 Unicode 输入,而且我不确定 TextTestRunner 是否能正确地将 Unicode 写入这个流。你也可以自己写一个内存流,来满足你的需求,可能需要用一个编码器来包装 StringIO

  2. 创建你自己的 TextTestRunner,并用这个内存流来初始化它。

  3. 创建一个类,从流中读取内容并将其写入日志。

这可以简单到:

class StreamLogger(object):
    def __init__(self, input_stream, output_logger):
        self.input_stream = input_stream
        self.output_logger
    def run(self):
        while True:
            line = input_stream.readline()
            if not line:
                break
            output_logger.error(line)

这种方法的问题:

  • 你在将 TextTestRunner 的不同输出部分导向不同日志级别时,几乎没有灵活性。
  • 如果 TextTestRunner 配置错误,它会写出很多你可能不想要的内容。默认的详细程度是 1,这会在测试时输出进度点……这可能会干扰你的日志输出。
  • 如果你简单粗暴地这样做,你会在写完所有输出到流后才调用 stream_logger.run()。这样,你就无法实时获取日志输出,日志的时间戳也没用。你可以通过启动一个单独的线程来读取来解决这个问题,但那样你需要选择一个可以同时处理读写线程的流,或者分叉一个进程,放弃内存流,这些都比较复杂。

我建议的做法是放弃流,直接创建一个自己的测试运行器——比如叫它 LoggingTestRunner——这样就可以按照你想要的方式将测试输出写入日志。这将帮助你避免上述三个问题。

撰写回答