Writing a pytest function for checking the output on console (stdout)

brain storm picture brain storm · Dec 11, 2013 · Viewed 11.3k times · Source

This link gives a description how to use pytest for capturing console outputs. I tried on this following simple code, but I get error

import sys
import pytest
def f(name):
    print "hello "+ name

def test_add(capsys):
    f("Tom")
    out,err=capsys.readouterr()
    assert out=="hello Tom"


test_add(sys.stdout)

Output:

python test_pytest.py 
hello Tom
Traceback (most recent call last):
  File "test_pytest.py", line 12, in <module>
    test_add(sys.stdout)
  File "test_pytest.py", line 8, in test_add
    out,err=capsys.readouterr()
AttributeError: 'file' object has no attribute 'readouterr'

what is wrong and what fix needed? thank you

EDIT: As per the comment, I changed capfd, but I still get the same error

import sys
import pytest
def f(name):
    print "hello "+ name

def test_add(capfd):
    f("Tom")
    out,err=capfd.readouterr()
    assert out=="hello Tom"


test_add(sys.stdout)

Answer

James Mills picture James Mills · Dec 11, 2013

Use the capfd fixture.

Example:

def test_foo(capfd):
    foo()  # Writes "Hello World!" to stdout
    out, err = capfd.readouterr()
    assert out == "Hello World!"

See: http://pytest.org/en/latest/fixture.html for more details

And see: py.test --fixtures for a list of builtin fixtures.

Your example has a few problems. Here is a corrected version:

def f(name):
    print "hello {}".format(name)


def test_f(capfd):
    f("Tom")

    out, err = capfd.readouterr()
    assert out == "hello Tom\n"

Note:

  • Do not use sys.stdout -- Use the capfd fixture as-is as provided by pytest.
  • Run the test with: py.test foo.py

Test Run Output:

$ py.test foo.py
====================================================================== test session starts ======================================================================
platform linux2 -- Python 2.7.5 -- pytest-2.4.2
plugins: flakes, cache, pep8, cov
collected 1 items 

foo.py .

=================================================================== 1 passed in 0.01 seconds ====================================================================

Also Note:

  • You do not need to run your Test Function(s) in your test modules. py.test (The CLI tool and Test Runner) does this for you.

py.test does mainly three things:

  1. Collect your tests
  2. Run your tests
  3. Display statistics and possibly errors

By default py.test looks for (configurable iirc) test_foo.py test modules and test_foo() test functions in your test modules.