pytest rerun only failed tests: --lf, --ff, -x, --sw (tested)
Run pytest --lf to rerun only the tests that failed last time (stored in .pytest_cache), pytest --ff to run them first and then the rest, -x to stop at the first failure, and --sw to step through failures one per run.
pytest remembers which tests failed in .pytest_cache (the built-in cacheprovider plugin), so you can rerun just those, run them first, or stop at the first failure. The test file below has two tests that fail until an environment variable "fixes" them; every command was run in order in the same directory on pytest 9.1.1.
The example: 2 of 4 tests fail
$ cat test_x.py
import os
def test_a():
pass
def test_b():
assert os.environ.get("FIXED_B")
def test_c():
pass
def test_d():
assert os.environ.get("FIXED_D")
$ pytest -q | tail -3
FAILED test_x.py::test_b - AssertionError: assert None
FAILED test_x.py::test_d - AssertionError: assert None
2 failed, 2 passed in 0.02s
1. Rerun only the failed tests: --lf (--last-failed)
$ pytest --lf | grep -E "run-last|passed|failed"
run-last-failure: rerun previous 2 failures
============================== 2 failed in 0.02s ===============================
The header line run-last-failure: rerun previous 2 failures confirms the cache was used; the two passing tests are not collected.
2. Fixed tests drop out of the list
$ FIXED_B=1 pytest -q --lf | tail -1
1 failed, 1 passed in 0.01s
$ pytest -q --lf | tail -1
1 failed in 0.01s
$ cat .pytest_cache/v/cache/lastfailed
{
"test_x.py::test_d": true
}
After test_b passes, it is removed from .pytest_cache/v/cache/lastfailed, so the next --lf runs only test_d. Fix tests one by one and keep running pytest --lf until it is empty.
3. When nothing failed, --lf runs everything (unless --lfnf none)
$ FIXED_B=1 FIXED_D=1 pytest -q | tail -1
4 passed in 0.00s
$ FIXED_B=1 FIXED_D=1 pytest --lf | grep -E "run-last|passed"
run-last-failure: no previously failed tests, not deselecting items.
============================== 4 passed in 0.01s ===============================
$ FIXED_B=1 FIXED_D=1 pytest --lf --lfnf none | grep -E "run-last|deselected"; echo "exit code: ${PIPESTATUS[0]}"
collected 4 items / 4 deselected / 0 selected
run-last-failure: no previously failed tests, deselecting all items.
============================ 4 deselected in 0.01s =============================
exit code: 5
With no recorded failures --lf runs the full suite. Add --lfnf none (--last-failed-no-failures none) to run nothing instead; note that this exits with code 5 (no tests collected), which fails a CI step.
4. Run failed tests first, then the rest: --ff (--failed-first)
$ pytest -q >/dev/null; pytest --ff -v | grep -E "^test_x.py::"
test_x.py::test_b FAILED [ 25%]
test_x.py::test_d FAILED [ 50%]
test_x.py::test_a PASSED [ 75%]
test_x.py::test_c PASSED [100%]
--ff still runs the whole suite, but you see the previously failing tests within the first seconds.
5. Stop at the first failure: -x and --maxfail
$ pytest -q -x | tail -2
!!!!!!!!!!!!!!!!!!!!!!!!!! stopping after 1 failures !!!!!!!!!!!!!!!!!!!!!!!!!!!
1 failed, 1 passed in 0.01s
$ pytest -q --maxfail=2 | tail -1
2 failed, 2 passed in 0.01s
-x is --maxfail=1. Combine with --lf (pytest --lf -x) to work through failures one at a time.
6. Fix failures one by one: --sw (--stepwise)
$ pytest -q --sw | tail -2
!!!!!!!! Interrupted: Test failed, continuing from this test next run. !!!!!!!!!
1 failed, 1 passed in 0.08s
$ FIXED_B=1 pytest -q --sw | tail -2
!!!!!!!! Interrupted: Test failed, continuing from this test next run. !!!!!!!!!
1 failed, 2 passed, 1 deselected in 0.07s
--sw stops at the first failure and, next run, starts from that test (the already-passing test_a was deselected). Each run moves forward to the next failure.
7. "unrecognized arguments: --lf"
$ pytest -q -p no:cacheprovider --lf 2>&1 | head -2
ERROR: usage: pytest [options] [file_or_dir] [file_or_dir] [...]
pytest: error: unrecognized arguments: --lf
--lf, --ff, --sw and --cache-clear all come from the cache plugin. If it is disabled with -p no:cacheprovider (sometimes set in addopts for read-only CI checkouts), the options do not exist. In CI, --lf also only helps if .pytest_cache is kept between runs; on a fresh checkout it has no failures to replay and runs everything. pytest --cache-clear deletes the stored results.
Related: pytest exit codes, pytest error: unrecognized arguments.
Frequently asked questions
How do I rerun only failed tests in pytest?
pytest --lf (--last-failed). It reads the failures recorded in .pytest_cache/v/cache/lastfailed from the previous run.
Why does pytest --lf run all tests?
No failures are recorded: the last run passed, .pytest_cache was deleted, or it is a fresh CI checkout. Use --lfnf none to run nothing in that case.
What is the difference between -x and --sw?
-x stops at the first failure. --sw also stops there but the next run resumes from that failing test instead of starting over.
Written with AI assistance. Measured on 2026-10-23 with pytest 9.1.1 on Python 3.13.5 in a clean virtualenv. Each block was run verbatim, in order, and the output pasted unedited. PlainHeaders is our extension; Python and pytest are free.