Writing a pytest function for checking the output on console (stdout)
Solution 1
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 thecapfd
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:
- Collect your tests
- Run your tests
- 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.
Solution 2
The problem is with your explicit call of your test function at the very end of your first code snippet block:
test_add(sys.stdout)
You should not do this; it is pytest's job to call your test functions.
When it does, it will recognize the name capsys
(or capfd
, for that matter)
and automatically provide a suitable pytest-internal object for you as a call argument.
(The example given in the pytest documentation is quite complete as it is.)
That object will provide the required readouterr()
function.
sys.stdout
does not have that function, which is why your program fails.
Related videos on Youtube
brain storm
Updated on July 03, 2022Comments
-
brain storm almost 2 years
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 errorimport 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)
-
brain storm over 10 yearsthis did not help. I get same error message. I pasted the code above for your reference
-
James Mills over 10 yearsWhat version of pytest are you using? Try upgrading. This works as expected and shown in all my unit tests.
-
brain storm over 10 yearsyou never call this function
test_f(capfd)
in your code, is that ok? -
James Mills over 10 yearsThe test runner and cli tool
py.test
does this for you. It does three things (mainly): 1) collect all your tests 2) run all your tests and 3) produces statistics and error output -
brain storm over 10 yearshow does it know which function to run for test? all functions with test_xxx?
-
James Mills over 10 yearsCorrect. THis is configrable IRRC but by default looks for
test_foo.py
modules andtest_foo()
function in those test modules.