在单元测试中隐藏stderr输出
我正在为一些代码写单元测试,这些代码使用 sys.stderr.write 来报告输入错误。这本来是对的,但这样会干扰单元测试的输出。有没有办法告诉 Python 不要输出某些命令的错误信息,就像在命令行中用 2> /dev/null
一样?
4 个回答
5
还有一种方法(除了直接把错误信息输出到 sys.stderr
)是把你的代码设计成可以把错误写入一个指定的文件,但默认情况下这个文件是 sys.stderr
。这样在测试的时候,你可以使用一个叫 DevNull 的写入器。
如果你确实想重新指定 sys.stderr
,可以使用 unittest 这个框架来帮你管理:
class DevNull(object):
def write(self, data):
pass
class MyTestCase(unittest.TestCase):
def setUp(self):
self.old_stderr = sys.stderr
sys.stderr = DevNull()
def tearDown(self):
sys.stderr = self.old_stderr
这样做的话,每次测试的时候都会把错误信息丢到一个无效的地方,但测试结束后又会把它恢复回来。
12
你可以创建一个虚假的文件对象,这个对象不会处理它的输出,然后把错误输出(stderr)设置为这个对象:
class NullWriter:
def write(self, s):
pass
sys.stderr = NullWriter()
如果你只想在特定的时间段内让错误输出安静下来,可以使用一个 with
语句,像这样:
class Quieter:
def __enter__(self):
self.old_stderr = sys.stderr
sys.stderr = NullWriter()
def __exit__(self, type, value, traceback):
sys.stderr = self.old_stderr
with Quieter():
# Do stuff; stderr will be suppressed, and it will be restored
# when this block exits
这个方法需要 Python 2.6 或更高版本,或者在 Python 2.5 中使用 from __future__ import with_statement
也可以。
26
我建议你写一个上下文管理器:
import contextlib
import sys
@contextlib.contextmanager
def nostderr():
savestderr = sys.stderr
class Devnull(object):
def write(self, _): pass
def flush(self): pass
sys.stderr = Devnull()
try:
yield
finally:
sys.stderr = savestderr
现在,把你想要隐藏错误信息的代码放在 with nostderr():
里面,这样就可以实现你想要的局部、临时、可逆的错误信息隐藏效果。