Skip to main content

A fast, drop-in compatible pytest runner written in Rust

Project description

pytest-rs

pytest-rs is a re-implementation of the popular Python testing framework pytest in Rust, focused on speed: a drop-in compatible runner where startup, collection, fixture orchestration, coverage measurement, and reporting are native code, while test bodies run on embedded CPython.

Note: This project is currently in active development (alpha stage). Many features are still under implementation and subject to change. See docs/DESIGN.md for the architecture and roadmap.

pytest-rs is an independent project, not affiliated with or endorsed by the pytest project.

Installation

Prebuilt wheels are published to PyPI for Linux (x86_64 / aarch64) and macOS (arm64) on CPython 3.13 / 3.14:

uv add --dev pytest-rs    # or: pip install pytest-rs

Then run your existing suite, no changes needed:

pytest-rs                       # whole suite, like `pytest`
pytest-rs tests/test_foo.py     # one file
pytest-rs -n 4                  # parallel workers (pytest-xdist compatible)
pytest-rs --cov=mypkg           # native coverage (pytest-cov compatible)

pytest-rs reads the same configuration pytest does (pytest.ini, pyproject.toml [tool.pytest] / [tool.pytest.ini_options], tox.ini, setup.cfg) and understands the familiar flags (-v, -x, -k, -m, --lf, --tb=..., -p no:NAME, ...). It installs alongside pytest without conflict — the pytest command is untouched.

Requirements

  • Linux or macOS (no Windows support yet)
  • CPython 3.13+ built with a shared libpython — true for uv-managed Pythons, python.org installers, Homebrew, conda, and distro packages. Plain pyenv builds need PYTHON_CONFIGURE_OPTS="--enable-shared" pyenv install ....

Bundled plugins

The compatibility layers for pytest-asyncio, anyio's pytest plugin, pytest-mock, pytest-cov, pytest-split, pytest-benchmark and pytest-xdist-style -n parallelism are built in — no separate plugin installs (the anyio layer runs tests through the installed anyio library's backends, so anyio itself must be in the environment as usual). Two ways to turn features off:

Per project or per run, like pytest (works with the prebuilt wheel):

[tool.pytest.ini_options]
addopts = "-p no:benchmark -p no:split"

At build time, when installing from source — bundled plugins are Cargo features, all enabled by default:

[tool.uv]
config-settings-package = { pytest-rs = { build-args = "--no-default-features --features asyncio,mock" } }

Third-party plugins (not reimplemented, loaded as-is)

Installed pytest11 entry points load through the pytest API shim — plugins pytest-rs does not reimplement can still work as-is. The supported surface includes fixtures, markers, pytest_addoption (plugin --flags and ini options), config.stash, custom hookspecs (pytest_addhooks), pytest_runtest_protocol/pytest_runtest_call hookwrappers, custom collectors (pytest_collect_fileFile/Item), and terminal-reporter replacement (a plugin that unregisters the terminalreporter plugin and registers its own subclass takes over the output — pytest-rs suppresses its native rendering and drives the replacement through the same hooks pluggy would). Verified status:

evidence plugins
own upstream test suite runs under pytest-rs and gates CI (per-suite pass-rate in the Third-party plugins conformance table below) pytest-timeout, pytest-randomly, pytest-env, pytest-socket, pytest-snapshot, pytest-ruff, pytest-rerunfailures, pytest-order, pytest-repeat, pytest-instafail, pytest-icdiff, pytest-metadata, pytest-subtests, pytest-mypy, pytest-bdd, pytest-django, pytest-aiohttp; anyio's own plugin module also loads this way
functional smoke demo gates CI (conformance/plugin_smoke.py) Faker, time-machine, requests-mock, inline-snapshot (snapshot assertions + --inline-snapshot flag), pytest-run-parallel (--parallel-threads really runs each test on N threads)
reporter replacement — terminal output byte-diffed against real pytest 9.0.3 pytest-pretty, pytest-sugar (progress bar, instant failures; activates on a tty or --force-sugar)
not reimplemented yet pytest-html (needs the report data model exposed); syrupy (serializer/extension framework)

A plugin that fails to import (e.g. it reaches into pytest/pluggy internals the shim doesn't provide) warns and is skipped without breaking the run. -p no:NAME and PYTEST_DISABLE_PLUGIN_AUTOLOAD opt out, like pytest.

Performance

Startup, collection, fixture orchestration, coverage measurement, and parallel workers are native Rust code. The main wins:

  • --cov runs — coverage is collected via sys.monitoring (Python 3.12+ low-overhead instrumentation) instead of coverage.py's tracing hooks. Typically 2–3x faster, and the gap widens with suite size.
  • -n parallel runs — workers are forked (not spawned), so each worker inherits a warm interpreter with all imports already done. Startup per worker drops from seconds to milliseconds.
  • Large collections — fixture resolution and parametrize expansion run in Rust; suites with thousands of tests see faster collection.

Benchmarks on open-source projects (macOS arm64, median of 3 warm runs), reproducible with bench/suites.sh — clones each suite at a pinned tag, installs pytest-rs into its venv, and times both runners.

suite (tests) mode pytest pytest-rs speedup
marshmallow (1119) (plain) 0.45 s 0.32 s 1.4x
marshmallow (1119) --cov 0.91 s 0.40 s 2.3x
marshmallow (1119) -n 3 --cov 1.11 s 0.33 s 3.4x
click (1336) (plain) 1.49 s 1.15 s 1.3x
click (1336) --cov 2.41 s 1.33 s 1.8x
click (1336) -n 3 --cov 2.44 s 0.77 s 3.2x
networkx (6890) (plain) 33.37 s 31.99 s 1.0x
networkx (6890) --cov 199.31 s 62.90 s 3.2x
networkx (6890) -n 3 --cov 80.14 s 29.25 s 2.7x

Small-to-medium suites see a 1.3–1.4x speedup even without coverage, thanks to lower startup overhead. On large suites where test bodies dominate, the plain-mode gap narrows; the bigger wins come from --cov and -n parallelism. Try it on your own suite:

hyperfine -w 1 'pytest -q' 'pytest-rs -q'
hyperfine -w 1 'pytest --cov=mypkg' 'pytest-rs --cov=mypkg'

Known limitations

  • unix only (no Windows)
  • no --pdb / debugger integration yet
  • third-party pytest plugins are loaded via the pytest11 entry point and the pytest API shim; plugins reaching deep into pytest internals may not work (see "Third-party plugins" above for verified examples)

Conformance testing

Compatibility is verified by running the upstream test suites of the libraries pytest-rs reproduces, unchanged, under pytest-rs (conformance/).

Current results (total = passed + failed + errors + skipped + deselected; deselected = tests intentionally skipped via --deselect in conformance/suites.toml, counted against total; files excluded = whole files that also fail under vanilla pytest, out of scope; updated automatically by conformance/runner.py — see conformance/RESULTS.md for per-file detail):

linux (CI-verified)

pytest & plugin ecosystem (the APIs pytest-rs reimplements):

suite tag passed failed errors skipped deselected total conformant % files all-pass files run files excluded
pytest 9.0.3 2584 204 0 53 8 2849 92.6% 21 54 61
pytest-asyncio v1.4.0 268 0 0 0 0 268 100.0% 30 30 0
pytest-mock v3.15.1 87 0 0 1 2 90 97.8% 1 1 0
pytest-cov v7.1.0 186 20 0 3 0 209 90.4% 0 1 0
pytest-xdist v3.8.0 97 0 0 1 0 98 100.0% 1 1 6
pytest-split 0.9.0 59 0 0 0 0 59 100.0% 1 1 3
pytest-benchmark v5.1.0 109 13 0 1 0 123 89.4% 4 7 6
anyio 4.13.0 3120 0 0 42 0 3162 100.0% 26 26 0

Third-party plugins (not reimplemented — their own upstream test suites run under pytest-rs, loaded via the pytest11 entry-point shim):

suite tag passed failed errors skipped deselected total conformant % files all-pass files run files excluded
pytest-aiohttp v1.1.1 6 0 0 0 1 7 85.7% 2 2 0
pytest-timeout 2.4.0 40 0 0 1 2 43 95.3% 1 1 0
pytest-mypy v1.0.1 53 23 0 2 0 78 70.5% 0 1 0
pytest-ruff v0.5 10 0 0 0 0 10 100.0% 1 1 0
pytest-subtests v0.14.2 32 0 0 0 0 32 100.0% 1 1 0
pytest-metadata v2.0.4 10 0 0 0 0 10 100.0% 1 1 0
pytest-snapshot v0.9.0 102 5 0 0 0 107 95.3% 0 3 0
pytest-icdiff 0.5 10 2 0 0 0 12 83.3% 0 1 0
pytest-socket 0.7.0 60 5 0 0 0 65 92.3% 3 6 0
pytest-order v1.4.0 120 14 0 0 0 134 89.6% 7 16 0
pytest-repeat v0.9.4 16 0 0 0 0 16 100.0% 1 1 0
pytest-instafail v0.5.0 63 0 0 0 0 63 100.0% 1 1 0
pytest-env 1.6.0 69 6 0 0 0 75 92.0% 2 3 0
pytest-rerunfailures 9.1.1 47 0 0 1 0 48 100.0% 1 1 0
pytest-randomly 4.1.0 30 7 0 0 0 37 81.1% 0 1 0
pytest-bdd 8.1.0 123 15 0 1 0 139 89.2% 28 35 0
pytest-django v4.9.0 205 10 0 1 0 216 95.4% 6 13 0

Real-world projects (their suites run unchanged, as drop-in evidence):

suite tag passed failed errors skipped deselected total conformant % files all-pass files run files excluded
click 8.3.1 1314 0 0 21 0 1335 100.0% 20 20 0
jinja 3.1.6 909 0 0 0 0 909 100.0% 22 22 0
marshmallow 4.1.1 1119 0 0 0 0 1119 100.0% 12 12 3
rich v14.2.0 855 0 0 25 0 880 100.0% 60 62 0
sqlglot v30.11.0 1120 0 0 0 0 1120 100.0% 52 54 0
httpx 0.28.1 1410 0 0 1 7 1418 99.5% 31 31 0
httpx2 v2.4.0 1426 0 0 1 0 1427 100.0% 31 31 0
starlette 0.46.2 907 0 0 0 0 907 100.0% 28 28 0
attrs 25.3.0 1341 0 0 4 1 1346 99.9% 22 24 0
more-itertools v10.7.0 670 0 0 1 0 671 100.0% 2 2 0
werkzeug 3.1.3 922 0 0 1 25 948 97.4% 24 25 0
fastapi 0.115.12 2332 1 0 130 1 2464 99.9% 303 310 0
packaging 25.0 26947 0 0 0 1 26948 100.0% 12 12 0
pandas v3.0.3 160773 1 0 26984 15 187773 100.0% 871 961 3
networkx 3.6.1 6815 0 0 79 0 6894 100.0% 259 266 0
pydantic v2.11.7 5338 14 0 921 0 6273 99.8% 77 82 0
scikit-learn-1 1.9.0 8432 0 0 6624 0 15056 100.0% 79 87 0
scikit-learn-2 1.9.0 5046 0 0 1892 0 6938 100.0% 52 58 0
scikit-learn-3 1.9.0 9251 3 0 2530 0 11784 100.0% 104 114 0

The suites are included as shallow git submodules under conformance/suites/ at the pinned release tags. Initialize them once after cloning:

git submodule update --init --depth 1

Then run the full conformance harness:

cargo build
uv run --no-project python conformance/runner.py --local   # uses submodules
uv run --no-project python conformance/runner.py           # re-clones from upstream (CI mode)
Project License Tag
pytest MIT 9.0.3
pytest-asyncio Apache-2.0 v1.4.0
pytest-mock MIT v3.15.1
pytest-cov MIT v7.1.0
pytest-xdist MIT v3.8.0
pytest-split MIT 0.9.0
pytest-benchmark BSD-2-Clause v5.1.0

pytest-rs reimplements the public APIs of these projects, plus anyio's pytest plugin (MIT). Parts of the bundled Python shims are ports of upstream code; see THIRD-PARTY-NOTICES.md. Credit for the API design and the test suites belongs to their respective authors.

License

This project is licensed under the MIT License. See the LICENSE file for more details.

Project details


Download files

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

Source Distribution

pytest_rs-0.0.7.tar.gz (594.6 kB view details)

Uploaded Source

Built Distributions

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

pytest_rs-0.0.7-cp314-cp314-manylinux_2_28_x86_64.whl (3.8 MB view details)

Uploaded CPython 3.14manylinux: glibc 2.28+ x86-64

pytest_rs-0.0.7-cp314-cp314-manylinux_2_28_aarch64.whl (3.6 MB view details)

Uploaded CPython 3.14manylinux: glibc 2.28+ ARM64

pytest_rs-0.0.7-cp314-cp314-macosx_11_0_arm64.whl (3.6 MB view details)

Uploaded CPython 3.14macOS 11.0+ ARM64

pytest_rs-0.0.7-cp313-cp313-manylinux_2_28_x86_64.whl (3.8 MB view details)

Uploaded CPython 3.13manylinux: glibc 2.28+ x86-64

pytest_rs-0.0.7-cp313-cp313-manylinux_2_28_aarch64.whl (3.6 MB view details)

Uploaded CPython 3.13manylinux: glibc 2.28+ ARM64

pytest_rs-0.0.7-cp313-cp313-macosx_11_0_arm64.whl (3.6 MB view details)

Uploaded CPython 3.13macOS 11.0+ ARM64

File details

Details for the file pytest_rs-0.0.7.tar.gz.

File metadata

  • Download URL: pytest_rs-0.0.7.tar.gz
  • Upload date:
  • Size: 594.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for pytest_rs-0.0.7.tar.gz
Algorithm Hash digest
SHA256 c38ba66ef3d20e618ba84ffd38dfa94f02e4f53548fd779e3c82ccd0aa840732
MD5 605e2c4ac8cec67bce004c535eaa8d07
BLAKE2b-256 81abdd042116e48fcbc64e25ed57367c8d26781e9926d29bb983d18782491cab

See more details on using hashes here.

Provenance

The following attestation bundles were made for pytest_rs-0.0.7.tar.gz:

Publisher: release.yml on Yasu-umi/pytest-rs

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

File details

Details for the file pytest_rs-0.0.7-cp314-cp314-manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for pytest_rs-0.0.7-cp314-cp314-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 3e3818edfe8258a9072e6de6bf50b49ed1beb39dc3311d19c40a656f0b0e6eba
MD5 7556da05e7195153f7d189fc9827321c
BLAKE2b-256 b1d59acf8025ec18d73245980c81b044c524bcb31e024b47d583a53e2cb3c7e0

See more details on using hashes here.

Provenance

The following attestation bundles were made for pytest_rs-0.0.7-cp314-cp314-manylinux_2_28_x86_64.whl:

Publisher: release.yml on Yasu-umi/pytest-rs

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

File details

Details for the file pytest_rs-0.0.7-cp314-cp314-manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for pytest_rs-0.0.7-cp314-cp314-manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 574b8b2dbd76a9af0e435ccc918f254b08d3b79d62900087462f404a80994128
MD5 6d3437ada716264fa26f7a1517dd9176
BLAKE2b-256 c378a4c93233ed7abd33a116910bdef2a0e01b4a60186e9a6d47cfe99c9c6d36

See more details on using hashes here.

Provenance

The following attestation bundles were made for pytest_rs-0.0.7-cp314-cp314-manylinux_2_28_aarch64.whl:

Publisher: release.yml on Yasu-umi/pytest-rs

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

File details

Details for the file pytest_rs-0.0.7-cp314-cp314-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for pytest_rs-0.0.7-cp314-cp314-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 a3434c3ae4373db6a847866c8f74286db53d5cb972afef624a68a6dd1b361e5b
MD5 4375b79d4fa4a3399c97c80e569e4265
BLAKE2b-256 2b7d742762d518ec2d5c5cac4f775c113a923671a176fb66ab51f79b7e84765b

See more details on using hashes here.

Provenance

The following attestation bundles were made for pytest_rs-0.0.7-cp314-cp314-macosx_11_0_arm64.whl:

Publisher: release.yml on Yasu-umi/pytest-rs

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

File details

Details for the file pytest_rs-0.0.7-cp313-cp313-manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for pytest_rs-0.0.7-cp313-cp313-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 b99ba55f996fb3df4d12a53120ec6783c9b4ffdae343623193846f27458b6324
MD5 c3d6153be26a8d88b2f8ba952bb9b23c
BLAKE2b-256 47a933f8dbd937aa615beeae9b64fadbd80bd6763bb4cff1593efc6d3c364680

See more details on using hashes here.

Provenance

The following attestation bundles were made for pytest_rs-0.0.7-cp313-cp313-manylinux_2_28_x86_64.whl:

Publisher: release.yml on Yasu-umi/pytest-rs

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

File details

Details for the file pytest_rs-0.0.7-cp313-cp313-manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for pytest_rs-0.0.7-cp313-cp313-manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 8e2458264b4d1d2507d42395b5e63843abd9faa0b819e0ef74f284c7fa98f3c6
MD5 32033c53af339448955facf71c47183f
BLAKE2b-256 95487d9851569367390be047ae92e251e8fa675d01d10165d7e6df287bfe2904

See more details on using hashes here.

Provenance

The following attestation bundles were made for pytest_rs-0.0.7-cp313-cp313-manylinux_2_28_aarch64.whl:

Publisher: release.yml on Yasu-umi/pytest-rs

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

File details

Details for the file pytest_rs-0.0.7-cp313-cp313-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for pytest_rs-0.0.7-cp313-cp313-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 9b30164a8bf0b9c3a4bc77c145bdb19043ad62153df3c352eee310737b10338c
MD5 d27e18a0d64608d2da31e0d42ae69ddb
BLAKE2b-256 2cc25ad8df361a27626e320cfe3f7dae5980b0d077cf50d2b739abcb6002048a

See more details on using hashes here.

Provenance

The following attestation bundles were made for pytest_rs-0.0.7-cp313-cp313-macosx_11_0_arm64.whl:

Publisher: release.yml on Yasu-umi/pytest-rs

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

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page