Every wizard knows that darkness is the enemy. When your tests fail and the traceback is a jumbled mess of cryptic runes, you need a spell to light the way. Welcome to Debugging with Pytest — the Lumos of the testing world.
Just as Lumos can shine at different intensities, pytest lets you control how much detail you see in tracebacks using --tb:
# Short traceback — a dim glow, just the essentials
pytest --tb=short
# Long traceback — full Lumos Maxima, every frame exposed
pytest --tb=long
# One line per failure — a flickering candle
pytest --tb=line
# No traceback at all — Nox! Darkness returns
pytest --tb=no
Use --tb=short when you're scanning many failures quickly (like skimming the Daily Prophet). Switch to --tb=long when you need to perform a full magical autopsy on a single cursed test.
Sometimes you don't want to watch the entire test suite crumble like a poorly cast Protego. Stop the carnage immediately:
# Stop at the FIRST failure — Impedimenta!
pytest -x
# Stop after N failures — controlled jinx
pytest --maxfail=3
This is essential during development: fix one curse at a time, like Madam Pomfrey treating one patient before moving to the next.
The Marauder's Map shows you exactly where everyone is. Similarly, pytest remembers which tests failed last time:
# Re-run ONLY the tests that failed last time
pytest --lf # "Last Failed" — I solemnly swear I am up to no good
# Run failed tests FIRST, then the rest
pytest --ff # "Failed First" — prioritize the troublemakers
This uses a cache file (.pytest_cache/) to track state between runs. Mischief managed.
Like using Sonorus to amplify your voice across the Quidditch pitch:
# Show each test name and result
pytest -v
# Even MORE detail — SONORUS MAXIMA
pytest -vv
With -vv, pytest shows full diffs for assertion failures, making it trivial to spot exactly which potion ingredient went wrong.
Sometimes you need to peer directly into your code's mind. --pdb drops you into Python's debugger at the exact point of failure:
# Cast Legilimens — enter the mind of the failing test
pytest --pdb
# Inside pdb, you can:
# (Pdb) p variable_name — inspect a variable
# (Pdb) l — list surrounding code
# (Pdb) n — next line
# (Pdb) c — continue execution
# (Pdb) q — quit
You're now a Legilimens, reading the program's memories at the moment of death. No Occlumency can hide the bug from you.
Some tests are like Gilderoy Lockhart — all show, no substance, and terribly slow. Find them:
# Show the 10 slowest tests
pytest --durations=10
# Show ALL test durations (including setup/teardown)
pytest --durations=0
This reveals which tests are hogging your Time-Turner. Optimize or split them before they slow your entire CI pipeline to a crawl.
Flaky tests are like Nifflers — unpredictable, occasionally destructive, and maddeningly hard to catch. Use pytest-rerunfailures:
# Install the taming charm
pip install pytest-rerunfailures
# Re-run failed tests up to 3 times
pytest --reruns 3
# Add a delay between reruns (for timing-sensitive tests)
pytest --reruns 3 --reruns-delay 2
# Or mark individual tests as flaky
import pytest
@pytest.mark.flaky(reruns=5, reruns_delay=1)
def test_niffler_behavior():
"""This test sometimes fails due to network gremlins."""
response = call_external_api()
assert response.status_code == 200
Remember: flaky tests are a symptom, not a feature. Tame the Niffler, don't just put it on a leash.
Sometimes the simplest debugging tool is a well-placed Howler (or print statement). But pytest captures stdout by default!
# Allow print output to appear (disable capture)
pytest -s
# Or use Python's logging module for more control
import logging
logger = logging.getLogger(__name__)
def test_with_logging():
logger.info("Starting the incantation...")
result = cast_spell("Expelliarmus")
logger.debug(f"Spell result: {result}")
assert result.success is True
# Run with log output visible:
pytest --log-cli-level=DEBUG
The -s flag is like removing a Silencing Charm from your tests. Suddenly, all those whispered print() statements ring out loud and clear, like a Howler in the Great Hall.
| Situation | Spell (Command) |
|---|---|
| Need less/more traceback | --tb=short/long/line/no |
| Stop at first failure | -x or --maxfail=N |
| Re-run only failures | --lf (last failed) |
| Failures first, then rest | --ff (failed first) |
| More output detail | -v or -vv |
| Drop into debugger | --pdb |
| Find slow tests | --durations=N |
| Handle flaky tests | --reruns N |
| See print output | -s |
| See log output | --log-cli-level=DEBUG |
"Happiness can be found, even in the darkest of times, if one only remembers to turn on the light." — Albus Dumbledore (and also anyone who remembers pytest --pdb).