丢弃被测程序的stdout/stderr,但保持unittest输出

dan*_*ast 5 python stdout stderr python-unittest

我有这个示例代码(test_it.py):

import sys

def give_me_5():
    print >>sys.stdout, "STDOUT"
    print >>sys.stderr, "STDERR"
    return 6

import unittest


class TestMe(unittest.TestCase):

    def setUp(self):
        pass

    def test_give_me_5(self):
        self.assertEqual(give_me_5(), 5)


if __name__ == '__main__':
    unittest.main()
Run Code Online (Sandbox Code Playgroud)

这给了我以下输出:

» python -m unittest test_it
A long annoying output message
A long annoying error message
F
======================================================================
FAIL: test_give_me_5 (__main__.TestMe)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "xx.py", line 17, in test_give_me_5
    self.assertEqual(give_me_5(), 5)
AssertionError: 6 != 5

----------------------------------------------------------------------
Ran 1 test in 0.000s

FAILED (failures=1)
Run Code Online (Sandbox Code Playgroud)

但由于被测程序产生的长而恼人的消息(真正的程序产生很多输出),我无法看到unittest的输出.我想摆脱正在测试的函数的stdout/stderr(give_me_5),但我仍然希望看到stdout/stderr unittest.我想得到这个结果:

» python -m unittest test_it
F
======================================================================
FAIL: test_give_me_5 (__main__.TestMe)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "xx.py", line 17, in test_give_me_5
    self.assertEqual(give_me_5(), 5)
AssertionError: 6 != 5

----------------------------------------------------------------------
Ran 1 test in 0.000s

FAILED (failures=1)
Run Code Online (Sandbox Code Playgroud)

因此,被测程序(stdout和stderr)产生的输出被unittest过滤掉,但是unittest本身产生的输出被保留了.我不想修改被测试的代码(代码本身没有重定向).我只想告诉unittest所有输出到stdout/stderr的输出应该被丢弃.

这可能吗?

sob*_*evn 5

@Alik建议是对的.但我想它可以改进.

import sys
# StringIO is replaced in Python 3:
try:
    from StringIO import StringIO
except ImportError:
    from io import StringIO

class ReplaceStd(object):
    """ Let's make it pythonic. """

    def __init__(self):
        self.stdout = None
        self.stderr = None

    def __enter__(self):
        self.stdout = sys.stdout
        self.stderr = sys.stderr

        # as it was suggseted already:
        sys.stdout = StringIO()
        sys.stderr = StringIO()

    def __exit__(self, type, value, traceback):
        sys.stdout = self.stdout
        sys.stderr = self.stderr

print('I am here')
with ReplaceStd():
    print('I am not')

print('I am back')
Run Code Online (Sandbox Code Playgroud)

并输出:

I am here
I am back
Run Code Online (Sandbox Code Playgroud)


Ali*_*lik 4

暂时将sys.stdout和替换sys.stderr为类似文件的实例。例如,您可以使用StringIO又名内存缓冲区。

from StringIO import StringIO

.....


class TestMe(unittest.TestCase):

    def setUp(self):
        pass

    def test_give_me_5(self):

        stdout = sys.stdout
        stderr = sys.stderr

        sys.stdout = StringIO()
        sys.stderr = StringIO()

        self.assertEqual(give_me_5(), 5)

        sys.stdout = stdout
        sys.stderr = stderr
Run Code Online (Sandbox Code Playgroud)

您可能想要添加异常处理,甚至将此代码放入上下文管理器中以重用它