I have this sample code (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()
Which gives me the following output:
» 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)
But because of the long, annoying messages produced by the program under test (the real program produces LOTS of output), I am unable to see the output from unittest. I would like to get rid of the stdout / stderr of the function being tested (give_me_5
), but I still want to see stdout / stderr of unittest
. I would like to get this result:
» 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)
So that the output produced by the program under test (both stdout and stderr) is filtered out by unittest, but the output produced by unittest itself is kept. I do not want to modify the code being tested (no redirection in the code itself). I just want to tell unittest that all output to stdout/stderr generated by the code under test should be discarded.
Is this possible?
@Alik suggestion was right. But I guess it could be improved.
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')
And the output:
I am here
I am back
Temporarily replace sys.stdout
and sys.stderr
with file-like instances. For example, you can use StringIO
aka memory buffers.
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
You might want to add exception handling or even turn this code in a context manager to reuse it
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With