Skip to main content

rstest

CI codecov PyPI Python versions Wheel License Downloads Docs GitHub stars

Run your existing pytest suite in parallel, unchanged. Same fixtures, same plugins, same outcomes — just faster. Rust-orchestrated, parallel by default, with built-in suite diagnostics (--doctor) that tell you where your test time actually goes.

aiohttp, 4,469 tests:   pytest 197s  →  rstest 68s warm (151s cold)

📚 Full documentation → python-rstest.readthedocs.io

Quick start

In any pytest project:

pip install rstest      # or: uv pip install rstest
rstest

Also works with your tool of choice:

uv add rstest           # uv projects
poetry add rstest       # Poetry
pdm add rstest          # PDM
pipx install rstest     # isolated CLI install

No config. No test changes. If pytest runs it, rstest runs it — in parallel (-n auto), out of the box.

  • Tests that can't run in parallel → @pytest.mark.serial (run exclusively, after the parallel phase).
  • Order-dependent suites → --dist loadfile.
  • Want byte-exact pytest semantics → rstest -n 0 (single pytest session).

Will rstest speed up your suite?

The wins come from suite shape, not magic. Quick self-check:

Your suite What to expect
Wait-bound (IO, sleeps, network, timeouts) Biggest win — test-granular dispatch splits the slow files xdist pins to one worker.
CPU-bound, already splits well under xdist Parity, not a win — gain up to core count, same as xdist (pandas: 63s vs 61s).
Gated by one long test No win beyond that test — no worker count beats the long pole. --doctor names it.
Small (< ~10s serial) Little wall-time change — value is --watch, --changed, --doctor, not raw speed.
Many tiny per-service suites Speedup is per-suite; the aggregate CI win depends on your largest suites.

Two more truths worth knowing before you benchmark:

  • Warm cache matters. Duration-aware scheduling needs one run of timing data. First run is cold; the win arrives on run two. In ephemeral CI, persist .rstest_cache or expect cold-run timing.
  • Adopting rstest adopts pytest 9. rstest runs a vendored pytest 9.1.1 core. A suite that's warning-clean on recent pytest 8.x is almost always already pytest-9-clean; if not, clear deprecations first (the same upgrade you'd owe pytest anyway). rstest -n 0 surfaces them.

Fastest way to find out for real: rstest --try runs your suite under plain pytest and under rstest -n auto, then reports whether outcomes match and how much faster rstest was — no migration, no config.

Benchmarks

Real open-source suites, end-to-end, with per-test outcome diffing against the pytest baseline — 100% parity on the measured run (a few tests flake under plain pytest itself; those are catalogued in the docs).

Suite Tests pytest xdist (-n 8) rstest
aiohttp 4,469 197s 160s 68s warm · 151s cold
pandas 193,627 182s 61s 63s (parity, not a win)
django-allauth 2,050 22s 8s 8s (-n 4)
rich 981 3.4s 2.8s 2.5s (-n 4)

Apple Silicon, CPython 3.13, pytest-xdist 3.8.

Monorepo (langchain-ai/langgraph, 6 libs/* packages, 4,284 tests, each with its own pytest config — a single pytest can't run from the root at all):

wall parity
pytest — 6 serial invocations 880.4s baseline
rstest at the root, cold 245.7s (3.6×) 100% (measured)
rstest at the root, warm 121–133s (6.6–7.3×) projected

The cold run is measured. The warm figure is a projection, not a recorded run — the cold run's per-package duration caches predict where the planner lands once warm, so it carries no parity number. Discount it until you measure your own.

Full methodology: benchmarks.

Why rstest

pytest pytest-xdist rstest
Runs your suite unchanged mostly
Parallel by default ⚙️ opt-in
Duration-aware scheduling
Crashed workers respawn mid-run
Suite diagnostics --doctor
Watch mode plugin ✅ built-in
  • Drop-in. Forwards the pytest flag surface; runs conftest, fixtures, parametrize, marks, and pytest plugins (pytest-django, pytest-asyncio, hypothesis, …) through a vendored pytest core.
  • Parallel by design. Test-granular work distribution with duration-aware scheduling; @pytest.mark.serial and --dist loadfile safety rails; crashed workers respawn without losing your run.
  • rstest --doctor. Wait-bound tests, parallel-floor analysis, fixture hotspots, slowest files.
  • rstest --watch. Instant reruns on save; changed test files rerun alone, source changes rerun only the tests the import graph says are affected.
Compatibility contract

At -n 0, outcomes are byte-exact — one vendored-pytest session; any difference at -n 0 is a bug. In parallel modes, outcomes are preserved for parallel-safe tests; tests with hidden time/ordering/shared-state assumptions can flake under high concurrency — exactly as under pytest-xdist. rstest --doctor and lower -n values help find and contain them; @pytest.mark.serial is the escape hatch.

Vendored pytest 9. rstest runs a vendored pytest 9.1.1 core, so adopting rstest adopts pytest 9's behavior regardless of the pytest version installed. The 8→9 gap is a cleanup major (removes already-deprecated APIs); a suite warning-clean on recent pytest 8.x is almost always pytest-9-clean. If it isn't, clear the deprecations first — the same upgrade you'd owe pytest anyway. There is one vendored core, tracked forward; no older-core build.

Silent-at--n ≥ 2 plugins. A few plugins that need a single master process are no-ops in parallel: --html (pytest-html) writes nothing (no crash) — generate reports at -n 0/-n 1. Terminal-UI plugins (pytest-sugar and friends) don't paint; data-level behavior is unaffected. Full list: Known gaps.

rstest --doctor

Runs your suite, then answers where does the time actually go? — from data the runner already owns (per-test wall/CPU time, per-fixture setup):

================== rstest doctor ==================
4442 tests, 185.8s test time (wall 67.7s, 8 workers)

WAIT-BOUND: 95% of test time (176.5s) is waiting, not computing (sleeps / IO / timeouts).
    54.20s waiting of   54.25s  tests/test_proxy_functional.py::test_proxy_https_multi_conn_limit
  ... and 33 more

PARALLEL FLOOR: the longest test (54.2s) exceeds the ideal per-worker share (23.2s at -n 8);
no worker count can finish faster than its longest test.

FIXTURE HOTSPOTS (setup time across all workers):
     0.79s   4442x  scope=function blockbuster

SLOWEST FILES:
   150.46s (81.0%)  tests/test_proxy_functional.py
===================================================

That's aiohttp's real suite — one file is 81% of total test time, almost all of it waiting on 10-second proxy timeouts. More →

Docs

License

Licensed under either of

at your option.

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

rstest-0.5.0-py3-none-win_arm64.whl (2.5 MB view details)

Uploaded Python 3Windows ARM64

rstest-0.5.0-py3-none-win_amd64.whl (2.7 MB view details)

Uploaded Python 3Windows x86-64

rstest-0.5.0-py3-none-musllinux_1_2_x86_64.whl (3.2 MB view details)

Uploaded Python 3musllinux: musl 1.2+ x86-64

rstest-0.5.0-py3-none-musllinux_1_2_aarch64.whl (3.0 MB view details)

Uploaded Python 3musllinux: musl 1.2+ ARM64

rstest-0.5.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (3.1 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ x86-64

rstest-0.5.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (3.0 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ ARM64

rstest-0.5.0-py3-none-macosx_11_0_arm64.whl (2.8 MB view details)

Uploaded Python 3macOS 11.0+ ARM64

File details

Details for the file rstest-0.5.0-py3-none-win_arm64.whl.

File metadata

  • Download URL: rstest-0.5.0-py3-none-win_arm64.whl
  • Upload date:
  • Size: 2.5 MB
  • Tags: Python 3, Windows ARM64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for rstest-0.5.0-py3-none-win_arm64.whl
Algorithm Hash digest
SHA256 3e2df09ac3bcd90e309bc1d7e18bd6291064f7e1b59cb9a5d8bc51410e40c94c
MD5 62b98ce515209d3cc663affee7d1da6b
BLAKE2b-256 084e8dfae95c0fe7008c6ec5d48f9f4dc60ff04fab502c67d06b51828ba8f6d9

See more details on using hashes here.

Provenance

The following attestation bundles were made for rstest-0.5.0-py3-none-win_arm64.whl:

Publisher: release.yml on KovantAI/rstest

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file rstest-0.5.0-py3-none-win_amd64.whl.

File metadata

  • Download URL: rstest-0.5.0-py3-none-win_amd64.whl
  • Upload date:
  • Size: 2.7 MB
  • Tags: Python 3, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for rstest-0.5.0-py3-none-win_amd64.whl
Algorithm Hash digest
SHA256 e58cedbbea8953f2c4d27796b1dd239376baf3b0b79287c0827ae50942046229
MD5 1e4453880fe8d8a5a46e46d90f2961b4
BLAKE2b-256 62194aa10f6dae0b97f8c62e21addcc12ad5e6efc351f76b9300097a75b486c7

See more details on using hashes here.

Provenance

The following attestation bundles were made for rstest-0.5.0-py3-none-win_amd64.whl:

Publisher: release.yml on KovantAI/rstest

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file rstest-0.5.0-py3-none-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for rstest-0.5.0-py3-none-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 80ff154398483999fc7bae419756f467c8ac9c3ceb0eba4de98a989b5f003eb1
MD5 d2cb8e4e2e8a28906b0781413bd5bc33
BLAKE2b-256 415d4b021a954acec0e5c1151163d6bf38bad91c9d70c29782f44d5f16d770b0

See more details on using hashes here.

Provenance

The following attestation bundles were made for rstest-0.5.0-py3-none-musllinux_1_2_x86_64.whl:

Publisher: release.yml on KovantAI/rstest

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file rstest-0.5.0-py3-none-musllinux_1_2_aarch64.whl.

File metadata

File hashes

Hashes for rstest-0.5.0-py3-none-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 10775bc981d7ee0829266051bd52794c9b0d4261f2d41674464707b40dee2ace
MD5 ba6af33c12223453be2b8fe0eadc57e6
BLAKE2b-256 6b478d99cb78b830b853085be2762aeedfc4ad9e5995bffb48da097d12c0071c

See more details on using hashes here.

Provenance

The following attestation bundles were made for rstest-0.5.0-py3-none-musllinux_1_2_aarch64.whl:

Publisher: release.yml on KovantAI/rstest

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file rstest-0.5.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for rstest-0.5.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 ddcfe49687cb0bbed385e2c135d03b1adf50cf65bab7a92d06e17c6939952aa9
MD5 a6a6aa83b1b9485af46596ecbb91819e
BLAKE2b-256 a5e77d1d10d9bae4bbe6317b894e7b4d1081ba8a05ba500637a51bee298422f7

See more details on using hashes here.

Provenance

The following attestation bundles were made for rstest-0.5.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: release.yml on KovantAI/rstest

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file rstest-0.5.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for rstest-0.5.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 760e3ca99b077e0a5f6c873a24832eb6e87622955ef3192674ba962868e53cc6
MD5 9374df4e3c1a4d0b448e8e1590c26d42
BLAKE2b-256 a95a0ee36821eb3b4f9868f88942cd490ee86f39de027bc12e0cc565070fdc3d

See more details on using hashes here.

Provenance

The following attestation bundles were made for rstest-0.5.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:

Publisher: release.yml on KovantAI/rstest

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file rstest-0.5.0-py3-none-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for rstest-0.5.0-py3-none-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 321622ba641e7d02a3fd764d65b991d3b5c829ca12be2efb8239ae98a52497ad
MD5 c136783235526df1dd4b9470c0472121
BLAKE2b-256 ada528fc5b892f8da01ef5fe492b969c3a24d4af4d6772cce92cd9d01803257f

See more details on using hashes here.

Provenance

The following attestation bundles were made for rstest-0.5.0-py3-none-macosx_11_0_arm64.whl:

Publisher: release.yml on KovantAI/rstest

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

0.5.0 This release

7 files

0.4.0

7 files

0.3.1

7 files

0.2.1

7 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page