Skip to main content

rstest

CI codecov PyPI Python versions Wheel License Downloads Docs GitHub stars

Runs most pytest suites unchanged, in parallel. Same fixtures, same plugins, parallel by default, with built-in suite diagnostics (--doctor) that tell you where your test time actually goes. How much faster depends on your suite's shape (self-check below).

Note: This is the Python test runner on PyPI (pip install rstest). It is not related to the Rust fixture crate rstest on crates.io.

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

aiohttp's suite: pytest 193s → rstest 67s on a warm cache, then --doctor shows where the time goes. Recorded at -n auto (14 workers); the suite gains nothing past 8, so the tables below use -n 8.

📚 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 --dev rstest           # uv projects
poetry add --group dev rstest # Poetry
pdm add -dG test rstest       # PDM

Install rstest into the same environment as your tests: workers run in that interpreter. A pipx / uv tool install alone can't run your tests; it only puts rstest on your PATH (details).

Requires Python 3.10+ on macOS (Apple silicon), Linux, or Windows (Windows is validated at a smaller scale than macOS/Linux). rstest is alpha (0.x): expect breaking changes between minor versions until 1.0.

No config and no test changes needed: rstest runs your pytest suite in parallel (-n auto) out of the box. As with pytest-xdist, session-scoped fixtures run once per worker, not once per run.

  • Tests that can't run in parallel (shared files, ports, databases) → @pytest.mark.serial (run exclusively, after the parallel phase).
  • Tests that depend on order within a file → --dist loadfile (keeps each file's tests on one worker); across files → rstest -n 0.
  • Want pytest's exact behavior → rstest -n 0 (single-worker mode: one pytest session, per-test outcomes match pytest exactly).

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: xdist's default --dist load hands out consecutive batches in collection order with no timing data, so a file of slow tests clusters on a few workers and starts late; rstest's duration cache starts the slowest tests first, spread across workers.
CPU-bound, already splits well under xdist Parity, not a win: gain up to the performance-core count, same as xdist (sympy -n 8: 16.1s vs 14.8s, overlapping spreads).
Very many tests (100k+) Win over xdist: xdist's single Python controller becomes the bottleneck; rstest's orchestrator is Rust (pandas -n 8: 43s vs 89s).
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 things to know 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, whatever pytest you have installed (details).

Fastest way to find out for real: rstest try compares a plain pytest run with rstest -n auto and reports parity and speed, with no config (how it works).

Benchmarks

Real open-source suites, end-to-end, with per-test outcome diffing against the pytest baseline: 100% parity on pandas, django-allauth and rich in the measured run (allauth and rich have tests that flake under plain pytest too, so some runs land at ~99.8-99.9%), and 99.91-99.98% on aiohttp, whose socket-leak warning flake hits xdist too (every known flake is catalogued in the docs).

Suite Tests pytest xdist -n 8 rstest -n 8
aiohttp 4,469 193s 160s (73s with --dist worksteal) 67s warm · 150s cold
pandas 193,843 190s 89s 43s (xdist's controller pins a core)
django-allauth 2,050 26s 8.9s 5.8s
rich 981 3.7s 2.7s 2.5s

Apple M4 Max, CPython 3.13, pytest-xdist 3.8, median of 5 runs at the same -n for both runners. CPU-bound suites (sympy, scikit-learn) land at parity with xdist; see the benchmarks page.

Monorepo (langchain-ai/langgraph, the 5 libs/* packages that need no live services, 838 tests, each with its own pytest config; a single pytest can't run from the root at all):

wall parity
pytest: 5 serial invocations 190.0s baseline
rstest at the root 26.1s (7.3×) 100%

Same method as above (median of 5, rstest -n auto). One of the five packages, libs/sdk-py, collects no tests under either runner in the benchmark venv (a missing test dependency), so the 838 tests come from the other four.

Full methodology: benchmarks.

Why rstest

pytest pytest-xdist rstest
Runs your suite unchanged ✅ parallel-safe tests parallel-safe tests; any suite at -n 0
Parallel by default ❌ ⚙️ opt-in ✅
Duration-aware scheduling plugin (pytest-split, across CI jobs) ❌ ✅
Crashed workers replaced mid-run ❌ ✅ ✅
Crash pinned to the exact test ❌ inferred from queue ✅ explicit per-test signal
Suite diagnostics ❌ ❌ ✅ --doctor
Watch mode plugin (pytest-watch) --looponfail (deprecated) ✅ built-in
  • Your tests, unchanged. A vendored pytest 9.1.1 core runs your conftest hierarchies, fixtures, parametrize, marks, and installed plugins (pytest-django, pytest-asyncio, hypothesis, pytest-mock, ...) as pytest does. Most pytest flags (-k, -m, -x, --lf, plugin flags) forward unchanged; a few, such as --timeout, --reruns and --html, are rstest's own with the same basic syntax as the plugins they replace.
  • xdist semantics in parallel. Session fixtures run once per worker, as under pytest-xdist, plus a short list of differences.
  • Parallel by design. Work distribution across worker processes, duration-aware scheduling that starts your slowest tests first (per test, or per file when a large suite gets lazy collection), and safety rails for tests that can't parallelize (@pytest.mark.serial, --dist loadfile).
  • Crash-safe. A segfaulting test costs you one FAILED line: the worker is replaced, its remaining tests redistribute, and the run completes.
  • rstest --doctor. Tells you why the suite is slow: tests that wait instead of compute, the long-pole tests that cap any parallelism, fixture hotspots, slowest files.
  • rstest --watch. 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 (single-worker mode) per-test outcomes match pytest exactly, and any difference is a bug (except for the few flags rstest shares with pytest or a plugin, which rstest handles itself at every worker count). In parallel, outcomes are preserved for parallel-safe tests, with the same caveats as pytest-xdist and a few report plugins that go quiet. Details: Compatibility and 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
    10.97s waiting of   10.97s  tests/test_proxy_functional.py::test_proxy_https_connect
  ... and 27 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. Gate tests:
    54.25s  tests/test_proxy_functional.py::test_proxy_https_multi_conn_limit

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

SLOWEST FILES:
   150.46s (81.0%)  tests/test_proxy_functional.py
     8.60s ( 4.6%)  tests/test_client_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. (Doctor counts tests with a recorded call duration, so skipped tests drop out: 4442 here against the 4,469 collected.) 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.9.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.9.0
File
rstest-0.9.0-py3-none-win_arm64.whl Python 3 none Windows ARM64 Details
rstest-0.9.0-py3-none-win_amd64.whl Python 3 none Windows x86-64 Details
rstest-0.9.0-py3-none-musllinux_1_2_x86_64.whl Python 3 none Linux musl 1.2+ x86-64 Details
rstest-0.9.0-py3-none-musllinux_1_2_aarch64.whl Python 3 none Linux musl 1.2+ ARM64 Details
rstest-0.9.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl Python 3 none Linux glibc 2.17+ x86-64 Details
rstest-0.9.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl Python 3 none Linux glibc 2.17+ ARM64 Details
rstest-0.9.0-py3-none-macosx_11_0_arm64.whl Python 3 none macOS 11.0+ ARM64 Details

Total release size: 32.7 MB

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

Download URL rstest-0.9.0-py3-none-win_arm64.whl
Size 4.1 MB
Tags Python 3 Windows ARM64
SHA-256 checksum
How to use checksums
51eefba6b4e15a0cde486ee1a0936c5743a0bb01bf864e1d2e076eda0a7eb18a
BLAKE2b-256 checksum
How to use checksums
f9a2e7e38ee2e97e4c662b94ea0effa65518b75cd7c48b235636868388b587f8
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 Oct 6, 2026.

Transparency log

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

Download URL rstest-0.9.0-py3-none-win_amd64.whl
Size 4.4 MB
Tags Python 3 Windows x86-64
SHA-256 checksum
How to use checksums
788c99bf6689340ed9c9440610b8368879be4fd19249c59ada7538601a633aa0
BLAKE2b-256 checksum
How to use checksums
66d00a937169178206fe507d5fb9e73e164fc968accf7d5f43e1c946f43a92f3
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 Oct 6, 2026.

Transparency log

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

Download URL rstest-0.9.0-py3-none-musllinux_1_2_x86_64.whl
Size 5.1 MB
Tags Linux musl 1.2+ x86-64 Python 3
SHA-256 checksum
How to use checksums
0bcf7d449f6a70199e001e0c8169dbb68281fda8dd9d7035e4cbe84e4e5e8ec0
BLAKE2b-256 checksum
How to use checksums
98dd8aca5eb3eea5730c64a42189ab83cd0655b050538695fa620ed6ad197c04
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 Oct 6, 2026.

Transparency log

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

Download URL rstest-0.9.0-py3-none-musllinux_1_2_aarch64.whl
Size 4.9 MB
Tags Linux musl 1.2+ ARM64 Python 3
SHA-256 checksum
How to use checksums
306a2b9753fb27cd486b9466139f01139d92c4d281c437d0b4f088ba3d34aeff
BLAKE2b-256 checksum
How to use checksums
25766876ee56dc22a42c3a93c700b25919728b60861e4139ff1c37b41e0e9a63
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 Oct 6, 2026.

Transparency log

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

Download URL rstest-0.9.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Size 4.9 MB
Tags Linux glibc 2.17+ x86-64 Python 3
SHA-256 checksum
How to use checksums
fbcbe6d1ea5726267b56fb835501ed276e509954874777808ddc078d30470f63
BLAKE2b-256 checksum
How to use checksums
cfa4b1d42a910a553c16fb13f37a2282fb5ef1160f58ca49ee65af3686ecca94
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 Oct 6, 2026.

Transparency log

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

Download URL rstest-0.9.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Size 4.9 MB
Tags Linux glibc 2.17+ ARM64 Python 3
SHA-256 checksum
How to use checksums
da9d9a4ea243c6e0cb14a13edc7d7d38ca7fdd2a6b96a4ce2fe0a966d6321266
BLAKE2b-256 checksum
How to use checksums
88c1fd42de9ea3df972051f20bd7f9efef45d8cbc33d85309f9b222c489571ae
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 Oct 6, 2026.

Transparency log

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

Download URL rstest-0.9.0-py3-none-macosx_11_0_arm64.whl
Size 4.5 MB
Tags Python 3 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
b21ecec9a17039d2fea493ee4d5086fa1bc7ef1cf4f64e73dfdb2e865d66d158
BLAKE2b-256 checksum
How to use checksums
bdcc6f185159cad9c3b8eba88468c5b17dc88a57d8bc8f305a423f984d0f7894
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 Oct 6, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.9.0 This release

7 release files

0.8.0

7 release files

0.7.0

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