我想在测试期间临时捕获发送到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)
我找到了similar question,但是接受的答案建议捕获所有测试用例发送到stdout
的消息。
是的,我知道对发送到stdout的消息进行单元测试不是很明智。是的,我也知道最好将logging
与assertLogs
结合使用。假设这两个选项在此阶段均不可用。
答案 0 :(得分:1)
解决方案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。为了模仿assertLogs
的行为,可以通过以下方法unittest.TestCase
扩展assertStdout
。
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
充当上下文管理器,并且单个消息将收集在output
列表中。扩展的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)
上面的代码产生以下输出:
======================================================================
FAIL: test_stdout (__main__.AnotherTest)
----------------------------------------------------------------------
Traceback (most recent call last):
File "executor_test.py", line 440, in test_stdout
self.assertIn("baz!", cm.output)
AssertionError: 'baz!' not found in ['foo!', 'bar!']