Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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) 
like image 426
brain storm Avatar asked Dec 10 '13 23:12

brain storm


People also ask

How do you record stdout output from a Python function call?

To capture stdout output from a Python function call, we can use the redirect_stdout function. to call redirect_stdout with the f StringIO object. Then we call do_something which prints stuff to stdout. And then we get the value printed to stdout with f.

How do you pytest a specific function?

Running pytest We can run a specific test file by giving its name as an argument. A specific function can be run by providing its name after the :: characters. Markers can be used to group tests. A marked grouped of tests is then run with pytest -m .

What is pytest check?

A pytest plugin that allows multiple failures per test. This pytest plugin was a rewrite and a rename of pytest-expect.


2 Answers

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.

like image 76
James Mills Avatar answered Oct 06 '22 01:10

James Mills


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.

like image 45
Lutz Prechelt Avatar answered Oct 06 '22 00:10

Lutz Prechelt