Debugging Failing Tests with pytest
This post briefly covers some tools for debugging failing tests when using pytest.
If looking at the traceback from a test failure isn’t enough there are a few tools to help debug a failing test:
-
The
--showlocals
argument to pytest will print out the values of all local variables after the traceback whenever a test fails. Sometimes this can be enough extra information to find the problem:$ tox -e py27-h tests/h -- --showlocals
-
Pytest will capture the output of any Python
print
statements and print it after the traceback for the failing test. The output ofprint
statements in the test code or in the code under test is printed (but print statements from tests that passed are not printed).Add
print
statements to the tests and to the code under test to print out information that can help you to figure out what’s going wrong - the values of arguments and local variables, which lines of code are called (and in which order), etc.Just remember to delete the
print
s again before committing the code!Tip: Try wrapping a
print
statement in anif
clause, so that something is printed out only if some expression is true. This can be useful for only printing out the valuable information, and not a lot of noise, if theprint
statement needs to be on a line of code that’s executed many times during the test. -
The
--pdb
argument to pytest will drop into a pdb debugger shell whenever a test fails, at the line of code that fails:$ tox -e py27-h tests/h -- --pdb
From this shell you can inspect the values of variables and arguments, evaluate expressions, step through code one line at a time, etc. For some tips see pdb on pymotw.
-
ipdb
is an enhanced debugger shell based on ipython, with syntax highlighting, tab completion, etc. To use it you first need to install ipdb into tox’s virtual environment:$ .tox/py27-h/bin/pip install robpol86-pytest-ipdb
We’re using
robpol86-pytest-ipdb
because thepytest-ipdb
package is broken.Then run the tests with the
--ipdb
argument instead of--pdb
:$ tox -e py27-h tests/h -- --ipdb
There are many more Python debuggers that you can try, for example pdb++ and pudb.
-
set_trace()
lets you drop into a debugger shell on any line of code, whether in a test or in the code under test, rather than just when a test fails. Put this line anywhere in the Python code:import pdb; pdb.set_trace()
and you’ll drop into pdb whenever execution hits that line.
For ipdb you would use
import ipdb; ipdb.set_trace()
.As with
print
statements, wrappingset_trace()
lines inif
statements can be a useful trick.As with
print
statements, remember to delete theset_trace()
lines again before committing the code. Fortunately you can easily grep the entire codebase forset_trace
, since this should never appear in production code.
All posts tagged “Python Unit Tests at Hypothesis”:
-
May 2017
Matcher Objects in Python Tests -
Apr 2017
When and When Not to Use Mocks -
Mar 2017
usefixtures as a Class Decorator -
Mar 2017
The Problem with Mocks -
Mar 2017
sentinel: Unique Objects for Tests -
Mar 2017
Hypothesis’s patch Fixture -
Mar 2017
Python’s unittest.mock -
Feb 2017
Advanced pytest Fixtures -
Feb 2017
Basic pytest Fixtures -
Jan 2017
Parametrizing Python Tests -
Jan 2017
Testing that an Exception is Raised with pytest.raises -
Jan 2017
Arrange, Act, Assert -
Jan 2017
Writing Simple Python Unit Tests -
Jan 2017
Debugging Failing Tests with pytest -
Jan 2017
Running the Hypothesis Python Tests -
Jan 2017
Python Unit Tests at Hypothesis