在单元测试中隐藏stderr输出

时间:2009-11-27 17:47:10

标签: python unit-testing

我正在编写一些使用sys.stderr.write来报告输入错误的代码的单元测试。这是应该的,但这会破坏单元测试输出。有没有办法告诉Python不输出单个命令的错误消息,àla2> /dev/null

4 个答案:

答案 0 :(得分:24)

我建议写一个上下文管理器:

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

现在,将您想要在其中抑制的stderr的任何代码段包装在with nostderr():中,并且您具有所需的本地化,临时,保证可逆的stderr抑制。

答案 1 :(得分:12)

您可以创建一个对其输出不执行任何操作的虚拟文件对象,并将stderr设置为:

class NullWriter:
    def write(self, s):
        pass

sys.stderr = NullWriter()

如果您只想在特定时间内安静stderr,可以使用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

答案 2 :(得分: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

这样,每个测试dev-null的stderr,但然后在测试结束时恢复它。

答案 3 :(得分:4)

class DevNull(object):
    def write(self, data): pass

sys.stderr = DevNull()

为了获得一个不那么永久的解决方案,可以找出类似如下的内容:

_stderr = None
def quiet():
    global _stderr
    if _stderr is None:
        _stderr = sys.stderr
        sys.stderr = DevNull()

def verbose():
   global _stderr
   if _stderr is not None:
       sys.stderr = _stderr
      _stderr = None

功能名称可能更好