Skip to content
rpytest GitHub

Home / Features

Everything rpytest does

rpytest keeps the pytest surface unchanged and adds exactly the machinery that removes per-invocation overhead — a warm daemon, built-in parallelism, and a verifier to prove it all still behaves like pytest. Here is the whole feature set, grouped by what it is for.

Drop-in compatibility

rpytest is pytest where pytest already works. Same surface, nothing to migrate.

pytest-shape CLI

rpytest mirrors pytest flags and selectors — -k, -m, --lf, -x, --maxfail, --collect-only, and node-ID selectors — so your existing invocations run unchanged.

Config read in place

pytest.ini, pyproject.toml ([tool.pytest.ini_options]), tox.ini, and setup.cfg are all read where they live. There is no rpytest config to migrate to.

Exit codes and JUnit XML match

Exit codes and JUnit XML match pytest exactly, so CI gates and report parsers keep working. Console stdout is similar but not byte-identical.

Warm daemon architecture

Interpreter startup, plugin import, and collection move from per-invocation to per-session cost.

Persistent Python daemon

The first invocation spawns a background Python process that imports your suite once and caches the collected node IDs; later invocations are small RPCs into a warm interpreter.

Real pytest under the hood

The daemon hosts a real pytest process. Your fixtures, conftest.py, parametrization, and hooks run in genuine pytest — they are not re-implemented.

Rust CLI, single-digit-MB footprint

The CLI is a small Rust binary (crates rpytest, rpytest-core, rpytest-ipc) that parses flags, applies selectors, and dispatches over IPC without paying Python overhead.

Parallel & CI

Built-in parallelism, sharding, and flakiness controls — no extra plugins.

Built-in -n auto

rpytest -n N and -n auto run tests across workers with duration-aware load balancing. No pytest-xdist install required; the flag surface matches.

Deterministic sharding

--shard 0 --total-shards 4 splits a suite deterministically across CI jobs, so shards are stable and reproducible.

Flakiness handling

--reruns N retries failing tests and --flaky-report surfaces quietly unreliable tests, without adding a rerun plugin.

Developer loop

The inner TDD loop, tightened around a warm daemon.

Watch mode

rpytest --watch re-runs the affected tests on each file change against the warm daemon, so a save triggers execution rather than a fresh collection.

Last-failed and selectors

--lf and keyword/marker selectors filter against the cached inventory, so re-running just what broke is near-instant.

Local by design

The daemon is a local process with no remote control plane. Manage it with --daemon-status, --daemon-stop, and --cleanup.

Confidence

Prove the swap is safe before you rely on it.

Drop-in verifier

rpytest --verify-dropin runs both pytest and rpytest and diffs collected node IDs, per-test outcomes, and exit codes — reporting exactly which tests disagree and whether at collection or execution time.

Honest benchmarks

The published BENCHMARK.md numbers come from one machine and a synthetic 500-test suite, presented as-is and not extrapolated. Measure your own suite with the verifier.

MIT-licensed, open source

rpytest is built by Neul Labs, MIT-licensed, with source on GitHub. A memory-safe Rust CLI over a real pytest core.

Ready to try it?

Install rpytest, run your suite, and prove parity with --verify-dropin.