Testing output to streams

In many situations, it’s perfectly legitimate for output to be printed to one of the standard streams. To aid with testing this kind of output, TestFixtures provides the OutputCapture helper.

This helper is a context manager that captures output sent to sys.stdout and sys.stderr and provides a compare() method to check that the output was as expected.

Here’s a simple example:

from testfixtures import OutputCapture
import sys

with OutputCapture() as output:
    # code under test
    print("Hello!")
    print("Something bad happened!", file=sys.stderr)

output.compare('\n'.join([
    "Hello!",
    "Something bad happened!",
]))

To make life easier, both the actual and expected output are stripped of leading and trailing whitespace before the comparison is done:

>>> with OutputCapture() as o:
...    print('  Bar! ')
...    o.compare(' Foo!  ')
Traceback (most recent call last):
...
AssertionError: 'Foo!' (expected) != 'Bar!' (actual)

However, if you need to make very explicit assertions about what has been written to the stream then you can do so using the captured property of the OutputCapture:

>>> with OutputCapture() as o:
...    print('  Bar! ')
>>> print(repr(o.captured))
'  Bar! \n'

If you need to explicitly check whether output went to stdout or stderr, separate mode can be used:

from testfixtures import OutputCapture
import sys

with OutputCapture(separate=True) as output:
    print("Hello!")
    print("Something bad happened!", file=sys.stderr)

output.compare(
    stdout="Hello!",
    stderr="Something bad happened!",
    )

Finally, you may sometimes want to disable an OutputCapture without removing it from your code. This often happens when you want to insert a debugger call while an OutputCapture is active; if it remains enabled, all debugger output will be captured making the debugger very difficult to use!

To deal with this problem, the OutputCapture may be disabled and then re-enabled as follows:

>>> with OutputCapture() as o:
...    print('Foo')
...    o.disable()
...    print('Bar')
...    o.enable()
...    print('Baz')
Bar
>>> print(o.captured)
Foo
Baz

Note

Some debuggers, notably pdb, do interesting things with streams such that calling disable() from within the debugger will have no effect. A good fallback is to type the following, which will almost always restore output to where you want it:

import sys; sys.stdout=sys.__stdout__