Home / Use cases / The TDD inner loop
Developer workflowThe TDD inner loop
Cut the save-run-read cycle from seconds to a fast RPC by keeping the interpreter and collection warm.
The problem
Test-driven development invokes the same suite dozens of times an hour. Plain pytest re-pays interpreter startup, plugin import, and test collection on every single run — so the loop that should feel instant instead stalls for a second or two each time, and the friction adds up across a session.
How rpytest solves it
- ▸The first rpytest run spawns the daemon and imports your suite once; every later run is a small RPC into a warm interpreter.
- ▸Run rpytest --watch and rpytest re-runs the affected tests on each file save against that warm daemon — no re-collection.
- ▸Combine with --lf (last-failed) so the inner loop re-runs only what just broke.
- ▸Fixtures, conftest.py, and plugins stay resident in the hosted real pytest, so behaviour is identical to what you already know.
$ rpytest --watch -k checkout [daemon warm · collection cached] watching src/ tests/ … # save a file → 3 passed, 1 failed in 0.11s
- ·The startup/collection cost is paid once per session, not once per run — that is where the loop time goes.
- ·Console output is similar but not byte-identical to pytest; exit codes match exactly.
Questions
+ Does watch mode re-collect the whole suite on every save?
No. The daemon keeps the collected node IDs cached and re-runs only the affected tests, so a save triggers execution, not a fresh collection.
+ Do my fixtures still behave the same across runs?
Yes — the daemon hosts a real pytest process, so fixtures, conftest.py, and parametrization run exactly as they do in pytest. Function- and module-scoped fixtures are set up and torn down per run as usual.