Python unittest:如何将标准输出消息临时重定向到缓冲区并测试其内容?

Python unittest:如何将标准输出消息临时重定向到缓冲区并测试其内容?,python,python-unittest,Python,Python Unittest,我想在测试期间捕获发送到stdout(我们的stderr)的消息,并断言这些消息中是否出现了某些字符串模式: import unittest class SomeTest(unittest.TestCase): def test_stdout(self): output = "" function_that_writes_to_stdout() # How to capture stdout in output temporarily?

我想在测试期间捕获发送到
stdout
(我们的
stderr
)的消息,并断言这些消息中是否出现了某些字符串模式:

import unittest
class SomeTest(unittest.TestCase):
    def test_stdout(self):
        output = ""
        function_that_writes_to_stdout()
        # How to capture stdout in output temporarily?
        self.assertIn("some message", output)
我找到了一个,但接受的答案建议捕获发送到所有测试用例的
stdout
的消息


是的,我知道对发送到stdout的消息进行单元测试不是很明智。是的,我也知道最好结合使用
日志记录
。让我们假设这两个选项在此阶段都不可用。

解决方案1。以下内容适用于我:

import io
import unittest
from contextlib import redirect_stdout

class Test(unittest.TestCase):
    def test_stdout(self):
        buf = io.StringIO()
        with redirect_stdout(buf):
            print("foo!")
        self.assertIn("foo", buf.getvalue())
buf.getvalue()
将包含整个输出,包括
\n
字符

解决方案2。为了模拟的行为,可以通过方法
assertStdout
扩展
unittest.TestCase
,如下所示

class StdoutRedirectionContext():
    class ListIO():
        def __init__(self):
            # Container for messages sent to stdout.
            self.output = []
        def write(self, s):
            # Filter empty strings or naked newline characters.
            if s in ("\n", ""): return
            self.output.append(s)

    def __enter__(self):
        self._buf = self.ListIO()
        self._ctx = redirect_stdout(self._buf)
        self._ctx.__enter__()
        return self._buf

    def __exit__(self, exc_type, exc_value, exc_traceback):
        self._ctx.__exit__(exc_type, exc_value, exc_traceback)

class TestCase(unittest.TestCase):
    def assertStdout(self):
        return StdoutRedirectionContext()
在这里,
StdoutRedirectionContext
充当上下文管理器,单个消息将收集在
输出
列表中。扩展的
TestCase
可按如下方式用于在stdout上断言消息:

class AnotherTest(TestCase):
    def test_stdout(self):
        with self.assertStdout() as cm:
            print("foo!")
            print("bar!")
        self.assertIn("foo!", cm.output)
        self.assertIn("baz!", cm.output)
上述结果产生以下输出:

======================================================================
失败:测试(主测试和其他测试)
----------------------------------------------------------------------
回溯(最近一次呼叫最后一次):
文件“executor_test.py”,第440行,在test_stdout中
断言(“baz!”,cm.output)
断言者错误:“baz!”在['foo!'、'bar!'中找不到