How to assert output with nosetest/unittest in python? How to assert output with nosetest/unittest in python? python python

How to assert output with nosetest/unittest in python?


I use this context manager to capture output. It ultimately uses the same technique as some of the other answers by temporarily replacing sys.stdout. I prefer the context manager because it wraps all the bookkeeping into a single function, so I don't have to re-write any try-finally code, and I don't have to write setup and teardown functions just for this.

import sysfrom contextlib import contextmanagerfrom StringIO import StringIO@contextmanagerdef captured_output():    new_out, new_err = StringIO(), StringIO()    old_out, old_err = sys.stdout, sys.stderr    try:        sys.stdout, sys.stderr = new_out, new_err        yield sys.stdout, sys.stderr    finally:        sys.stdout, sys.stderr = old_out, old_err

Use it like this:

with captured_output() as (out, err):    foo()# This can go inside or outside the `with` blockoutput = out.getvalue().strip()self.assertEqual(output, 'hello world!')

Furthermore, since the original output state is restored upon exiting the with block, we can set up a second capture block in the same function as the first one, which isn't possible using setup and teardown functions, and gets wordy when writing try-finally blocks manually. That ability came in handy when the goal of a test was to compare the results of two functions relative to each other rather than to some precomputed value.


If you really want to do this, you can reassign sys.stdout for the duration of the test.

def test_foo():    import sys    from foomodule import foo    from StringIO import StringIO    saved_stdout = sys.stdout    try:        out = StringIO()        sys.stdout = out        foo()        output = out.getvalue().strip()        assert output == 'hello world!'    finally:        sys.stdout = saved_stdout

If I were writing this code, however, I would prefer to pass an optional out parameter to the foo function.

def foo(out=sys.stdout):    out.write("hello, world!")

Then the test is much simpler:

def test_foo():    from foomodule import foo    from StringIO import StringIO    out = StringIO()    foo(out=out)    output = out.getvalue().strip()    assert output == 'hello world!'


Since version 2.7, you do not need anymore to reassign sys.stdout, this is provided through buffer flag. Moreover, it is the default behavior of nosetest.

Here is a sample failing in non buffered context:

import sysimport unittestdef foo():    print 'hello world!'class Case(unittest.TestCase):    def test_foo(self):        foo()        if not hasattr(sys.stdout, "getvalue"):            self.fail("need to run in buffered mode")        output = sys.stdout.getvalue().strip() # because stdout is an StringIO instance        self.assertEquals(output,'hello world!')

You can set buffer through unit2 command line flag -b, --buffer or in unittest.main options.The opposite is achieved through nosetest flag --nocapture.

if __name__=="__main__":       assert not hasattr(sys.stdout, "getvalue")    unittest.main(module=__name__, buffer=True, exit=False)    #.    #----------------------------------------------------------------------    #Ran 1 test in 0.000s    #    #OK    assert not hasattr(sys.stdout, "getvalue")    unittest.main(module=__name__, buffer=False)    #hello world!    #F    #======================================================================    #FAIL: test_foo (__main__.Case)    #----------------------------------------------------------------------    #Traceback (most recent call last):    #  File "test_stdout.py", line 15, in test_foo    #    self.fail("need to run in buffered mode")    #AssertionError: need to run in buffered mode    #    #----------------------------------------------------------------------    #Ran 1 test in 0.002s    #    #FAILED (failures=1)