[英]Python unittest: How to temporarily redirect stdout messages to a buffer and to test its content?
I would like to capture messages sent to stdout
(our stderr
) temporarily during a test and assert if some string patterns occurred in these messages:我想在测试期间临时捕获发送到
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)
I found a similar question , but the accepted answer suggests to capture messages sent to stdout
for all test cases.我发现了一个类似的问题,但接受的答案建议为所有测试用例捕获发送到
stdout
消息。
Yes, I know that it's not very smart to unittest messages sent to stdout.是的,我知道对发送到标准输出的消息进行单元测试并不是很聪明。 And yes, I also know that it'd be better to use
logging
in combination with assertLogs
.是的,我也知道最好将
logging
与assertLogs
结合使用。 Let's assume that both options are not available at this stage.让我们假设这两个选项在此阶段都不可用。
Solution 1. The following worked for me:解决方案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()
will contain the entire output, including \\n
characters. buf.getvalue()
将包含整个输出,包括\\n
字符。
Solution 2. To mimic the behavior of assertLogs
, one can extend unittest.TestCase
by a method assertStdout
as follows.解决方案 2.为了模仿
assertLogs
的行为,可以通过方法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()
Here, StdoutRedirectionContext
acts a context manager, and the single messages will be collected in the output
list.在这里,
StdoutRedirectionContext
充当上下文管理器,单个消息将被收集在output
列表中。 The extended TestCase
can be used as follows to assert messages on stdout:扩展的
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)
The above yields the following 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!']
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.