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 (126s cold)

Terminal recording: the aiohttp suite under pytest (197s), then rstest (68s, 8 parallel workers), then rstest --doctor pinpointing the wait-bound file that gates the suite

Same suite, same outcomes: pytest 197s → rstest 68s (warm, -n 8), then --doctor shows where the time goes. Numbers from benchmarks.

📚 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 · 126s 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.

Metadata

Release files for rstest 0.7.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Built distributions (wheels)

Table of built distributions (wheels) for rstest 0.7.0
File
rstest-0.7.0-py3-none-win_arm64.whl Python 3 none Windows ARM64 Details
rstest-0.7.0-py3-none-win_amd64.whl Python 3 none Windows x86-64 Details
rstest-0.7.0-py3-none-musllinux_1_2_x86_64.whl Python 3 none Linux musl 1.2+ x86-64 Details
rstest-0.7.0-py3-none-musllinux_1_2_aarch64.whl Python 3 none Linux musl 1.2+ ARM64 Details
rstest-0.7.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl Python 3 none Linux glibc 2.17+ x86-64 Details
rstest-0.7.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl Python 3 none Linux glibc 2.17+ ARM64 Details
rstest-0.7.0-py3-none-macosx_11_0_arm64.whl Python 3 none macOS 11.0+ ARM64 Details

Total release size: 28.1 MB

Release files / rstest-0.7.0-py3-none-win_arm64.whl

Download URL rstest-0.7.0-py3-none-win_arm64.whl
Size 3.5 MB
Tags Python 3 Windows ARM64
SHA-256 checksum
How to use checksums
075e1bf13356eda572ab43f7d183d90c3e573ad75540e99d3f8b0289e2445701
BLAKE2b-256 checksum
How to use checksums
1e3f3f4bb57b72eb292b82c20e9ac9a0522322787724ca350e88fa8a64957136
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 10, 2026.

Transparency log

Release files / rstest-0.7.0-py3-none-win_amd64.whl

Download URL rstest-0.7.0-py3-none-win_amd64.whl
Size 3.7 MB
Tags Python 3 Windows x86-64
SHA-256 checksum
How to use checksums
41681d5f0cb452b07b17a90c8bff2beee2b0cc12cbf90b9b3534eed420bac123
BLAKE2b-256 checksum
How to use checksums
9fa7396fc08f09d30b72103112537b82fd4779e479b7306c936e5e5a8b02378b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 10, 2026.

Transparency log

Release files / rstest-0.7.0-py3-none-musllinux_1_2_x86_64.whl

Download URL rstest-0.7.0-py3-none-musllinux_1_2_x86_64.whl
Size 4.4 MB
Tags Linux musl 1.2+ x86-64 Python 3
SHA-256 checksum
How to use checksums
46fe79feab68bb36eb3ab45ce60083a72c45a529cb124ebb9d4cafa8d8cb1bb4
BLAKE2b-256 checksum
How to use checksums
5d923842ae87c46052aa76dcdea0f23aa658ec716fd3008b0a4506681938ab8c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 10, 2026.

Transparency log

Release files / rstest-0.7.0-py3-none-musllinux_1_2_aarch64.whl

Download URL rstest-0.7.0-py3-none-musllinux_1_2_aarch64.whl
Size 4.2 MB
Tags Linux musl 1.2+ ARM64 Python 3
SHA-256 checksum
How to use checksums
bed196652ed1657dc002afa85f4ea936c1cb545a4010d624fa34a67d02b0f933
BLAKE2b-256 checksum
How to use checksums
efcc647fbcb57f0b7f42e0d5f4a3571e02d8840b13a45f66b20afef1cd446f0b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 10, 2026.

Transparency log

Release files / rstest-0.7.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL rstest-0.7.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Size 4.2 MB
Tags Linux glibc 2.17+ x86-64 Python 3
SHA-256 checksum
How to use checksums
ddbff5ba8c129896fa3fbbef18aa8377e8cb9d1c095c2c7c642c8988a10d2fe3
BLAKE2b-256 checksum
How to use checksums
79f6f6ab0ce2e2f741d962f7f2073b886bbd1374c9fdbc7d61cceebc46f561f5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 10, 2026.

Transparency log

Release files / rstest-0.7.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl

Download URL rstest-0.7.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Size 4.2 MB
Tags Linux glibc 2.17+ ARM64 Python 3
SHA-256 checksum
How to use checksums
6a738d37f0ad082d53a8cc03eefd6595bbdf0c5f8c115ca98a137ce99a0a165d
BLAKE2b-256 checksum
How to use checksums
f24f77dcc2616bbc9c5211f3be82f2417621c5559fd891ea0b5b568e92906ab4
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 10, 2026.

Transparency log

Release files / rstest-0.7.0-py3-none-macosx_11_0_arm64.whl

Download URL rstest-0.7.0-py3-none-macosx_11_0_arm64.whl
Size 3.8 MB
Tags Python 3 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
5355a0a6c233f4e9536ed2d7b1558afc623214838f8696b1e8f95e8d4176fce4
BLAKE2b-256 checksum
How to use checksums
1ebf11c5ef9c6336a1d2eb26061fe2be88b8d31b6dada2fde5c6a3dd7842d3f3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 10, 2026.

Transparency log

Release history Release notifications | RSS feed

0.9.0

7 release files

0.8.0

7 release files

This release

0.7.0 This release

7 release files

0.6.1

7 release files

0.5.0

7 release files

0.4.0

7 release files

0.3.1

7 release files

0.2.1

7 release 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