How to print to console in pytest?
Solution 1
By default, py.test
captures the result of standard out so that it can control how it prints it out. If it didn't do this, it would spew out a lot of text without the context of what test printed that text.
However, if a test fails, it will include a section in the resulting report that shows what was printed to standard out in that particular test.
For example,
def test_good():
for i in range(1000):
print(i)
def test_bad():
print('this should fail!')
assert False
Results in the following output:
>>> py.test tmp.py
============================= test session starts ==============================
platform darwin -- Python 2.7.6 -- py-1.4.20 -- pytest-2.5.2
plugins: cache, cov, pep8, xdist
collected 2 items
tmp.py .F
=================================== FAILURES ===================================
___________________________________ test_bad ___________________________________
def test_bad():
print('this should fail!')
> assert False
E assert False
tmp.py:7: AssertionError
------------------------------- Captured stdout --------------------------------
this should fail!
====================== 1 failed, 1 passed in 0.04 seconds ======================
Note the Captured stdout
section.
If you would like to see print
statements as they are executed, you can pass the -s
flag to py.test
. However, note that this can sometimes be difficult to parse.
>>> py.test tmp.py -s
============================= test session starts ==============================
platform darwin -- Python 2.7.6 -- py-1.4.20 -- pytest-2.5.2
plugins: cache, cov, pep8, xdist
collected 2 items
tmp.py 0
1
2
3
... and so on ...
997
998
999
.this should fail!
F
=================================== FAILURES ===================================
___________________________________ test_bad ___________________________________
def test_bad():
print('this should fail!')
> assert False
E assert False
tmp.py:7: AssertionError
====================== 1 failed, 1 passed in 0.02 seconds ======================
Solution 2
Short Answer
Use the -s
option:
pytest -s
Detailed answer
From the docs:
During test execution any output sent to stdout and stderr is captured. If a test or a setup method fails its according captured output will usually be shown along with the failure traceback.
pytest
has the option --capture=method
in which method
is per-test capturing method, and could be one of the following: fd
, sys
or no
. pytest
also has the option -s
which is a shortcut for --capture=no
, and this is the option that will allow you to see your print statements in the console.
pytest --capture=no # show print statements in console
pytest -s # equivalent to previous command
Setting capturing methods or disabling capturing
There are two ways in which pytest
can perform capturing:
file descriptor (FD) level capturing (default): All writes going to the operating system file descriptors 1 and 2 will be captured.
sys level capturing: Only writes to Python files sys.stdout and sys.stderr will be captured. No capturing of writes to filedescriptors is performed.
pytest -s # disable all capturing
pytest --capture=sys # replace sys.stdout/stderr with in-mem files
pytest --capture=fd # also point filedescriptors 1 and 2 to temp file
Solution 3
Using -s
option will print output of all functions, which may be too much.
If you need particular output, the doc page you mentioned offers few suggestions:
Insert
assert False, "dumb assert to make PyTest print my stuff"
at the end of your function, and you will see your output due to failed test.-
You have special object passed to you by PyTest, and you can write the output into a file to inspect it later, like
def test_good1(capsys): for i in range(5): print i out, err = capsys.readouterr() open("err.txt", "w").write(err) open("out.txt", "w").write(out)
You can open the
out
anderr
files in a separate tab and let editor automatically refresh it for you, or do a simplepy.test; cat out.txt
shell command to run your test.
That is rather hackish way to do stuff, but may be it is the stuff you need: after all, TDD means you mess with stuff and leave it clean and silent when it's ready :-).
Solution 4
This is the cleanest way I know to print a single statement to sys.stdout
(without artificially making your test fail or enabling the -s
option) - you get to see the specific output you want and nothing more:
- Add the in-built parameter
capsys
to your test function. (This means that you addcapsys
to the list of parameters, e.g.
def test_function(existing_parameters, capsys):
- In your code, simply insert:
with capsys.disabled():
print("this output will not be captured and go straight to sys.stdout")
See https://buildmedia.readthedocs.org/media/pdf/pytest/latest/pytest.pdf (2.11 How to capture stdout/stderr output).
Solution 5
I needed to print important warning about skipped tests exactly when PyTest
muted literally everything.
I didn't want to fail a test to send a signal, so I did a hack as follow:
def test_2_YellAboutBrokenAndMutedTests():
import atexit
def report():
print C_patch.tidy_text("""
In silent mode PyTest breaks low level stream structure I work with, so
I cannot test if my functionality work fine. I skipped corresponding tests.
Run `py.test -s` to make sure everything is tested.""")
if sys.stdout != sys.__stdout__:
atexit.register(report)
The atexit
module allows me to print stuff after PyTest
released the output streams. The output looks as follow:
============================= test session starts ==============================
platform linux2 -- Python 2.7.3, pytest-2.9.2, py-1.4.31, pluggy-0.3.1
rootdir: /media/Storage/henaro/smyth/Alchemist2-git/sources/C_patch, inifile:
collected 15 items
test_C_patch.py .....ssss....s.
===================== 10 passed, 5 skipped in 0.15 seconds =====================
In silent mode PyTest breaks low level stream structure I work with, so
I cannot test if my functionality work fine. I skipped corresponding tests.
Run `py.test -s` to make sure everything is tested.
~/.../sources/C_patch$
Message is printed even when PyTest
is in silent mode, and is not printed if you run stuff with py.test -s
, so everything is tested nicely already.
BBedit
Updated on July 15, 2022Comments
-
BBedit almost 2 years
I'm trying to use TDD (test-driven development) with
pytest
.pytest
will notprint
to the console when I useprint
.I am using
pytest my_tests.py
to run it.The
documentation
seems to say that it should work by default: http://pytest.org/latest/capture.htmlBut:
import myapplication as tum class TestBlogger: @classmethod def setup_class(self): self.user = "alice" self.b = tum.Blogger(self.user) print "This should be printed, but it won't be!" def test_inherit(self): assert issubclass(tum.Blogger, tum.Site) links = self.b.get_links(posts) print len(links) # This won't print either.
Nothing gets printed to my standard output console (just the normal progress and how many many tests passed/failed).
And the script that I'm testing contains print:
class Blogger(Site): get_links(self, posts): print len(posts) # It won't get printed in the test.
In
unittest
module, everything gets printed by default, which is exactly what I need. However, I wish to usepytest
for other reasons.Does anyone know how to make the print statements get shown?
-
U.V. over 5 yearsi tried version 1. with pytest 3.8.1 unfortunately it only prints the test function block, but not the output from print statements :( any more tricks for this?
-
z0r over 4 yearsPerfect for outputting custom test metrics.
-
Tim Boland over 4 yearshmm...still doesnt log my print statements
-
Mart Van de Ven almost 4 years@U.V. - Instead of using the
print()
function, you should put the variable or message you mean to print after the comma in the assert statement. E.g.assert False, what_are_you
will 'print out' the value ofwhat_are_you
in the pytest report. -
Sukma Saputra almost 4 yearsIt's work for me when need print variable in terminal...
-
0 _ almost 3 yearsTo pass the
--capture
option in every run ofpytest
, add the lineaddopts = --capture=tee-sys
in the section[pytest]
within the filepytest.ini
(documentation). -
pabouk - Ukraine stay strong over 2 yearsThis should be the preferred answer! It seems to work flawlessly without side-effects.
-
Karimai over 2 yearsjust in this way I can see my print logs. I did not see the print log by -s option nor by creating a file.
-
Bernd Wechner about 2 yearsIt would help if "Add the in-built parameter capsys to your test function." included a little more detail for noobs ... I have no idea what that means off hand.
-
CodePrinz about 2 yearsedit queue is full, can't edit: it is really just
def test_something(capsys): ...
See docs.pytest.org/en/6.2.x/fixture.html. -
Sacha about 2 years@BerndWechner, thank you for the suggestion, I've edited the answer.