pytest-fsplit
pytest-fsplit is a pytest plugin for splitting a test suite into deterministic
file-level shards before pytest imports and collects unselected files. This is in contrast with plugins like pytest-split which collect fully and then deselect in each shard. In large test code bases this collection step can take up multiple minutes and keeps taking longer as you add more tests. In pytest-fsplit the collection is a lot faster and stays proportional to shard size. In our own codebase with 18k tests and 1.5k test files, pytest-fsplit takes 40s vs pytest-split which takes 3 mins to collect tests.
pytest-fsplit reads a pytest-split-compatible JSON duration file, aggregates node timings by
test file, assigns files to shards with a longest-processing-time-first plan, and
uses pytest_ignore_collect to prune files and directories outside the selected
shard.
Installation
pip install pytest-fsplit
Usage
First record durations from a complete, unsharded run:
pytest --fsplit-store-durations
Then run each file shard separately:
pytest --fsplits 4 --fgroup 1
pytest --fsplits 4 --fgroup 2
pytest --fsplits 4 --fgroup 3
pytest --fsplits 4 --fgroup 4
The duration file defaults to .test_durations in the invocation directory and
can be changed with --fsplit-durations-path.
pytest-fsplit intentionally uses distinct option names. If pytest-split is
installed too, --splits and --group continue to belong to pytest-split; use
--fsplits and --fgroup for file-level pre-collection sharding.
The default file splitting algorithm is least_duration, which greedily assigns
the next heaviest file to the lightest shard. To preserve contiguous lexical file
order instead, use duration_based_chunks:
pytest --fsplits 4 --fgroup 1 --fsplit-algorithm duration_based_chunks
When nbval is active through --nbval or --nbval-lax, pytest-fsplit treats
.ipynb notebooks as shardable files automatically. For other non-Python
collectors, provide the file patterns pytest-fsplit should treat as shardable
files:
pytest --fsplit-file-pattern "*.case" --fsplits 4 --fgroup 1
Stored duration files can be inspected from the command line:
fsplit-plan --fsplits 4
fsplit-slowest-tests --count 10
slowest-tests --count 10
fsplit-slowest-files --count 10
Use fsplit-plan --fsplits 4 --show-files to see file assignments, or
fsplit-plan --fsplits 4 --json for machine-readable output.
Behavior
- Shard indices are one-based.
- Both
--fsplitsand--fgroupmust be supplied together. - If there are more shards than candidate files, planned empty shards exit successfully.
--fsplit-algorithmsupportsleast_durationandduration_based_chunks.- Files without historical timings use the median known file duration.
- Stale timing entries for deleted files are ignored.
- Missing, malformed, or unusable duration files fail immediately when sharding.
--fsplit-store-durationswrites the same node-duration JSON shape used by pytest-split.- Older pytest-split list-of-pairs duration files are accepted when reading.
--fsplit-store-durationscannot be combined with sharding because it would record only the selected shard.--fsplit-clean-durationsis valid only with--fsplit-store-durations.
Compatibility
pytest-fsplit runs before collection, so it avoids the full-suite collection
cost paid by post-collection splitters. It honors pytest collection roots,
python_files, --ignore, --ignore-glob, norecursedirs, explicit file
arguments, marker deselection, and xdist worker startup.
If pytest-split is installed too, do not combine --fsplits/--fgroup with
pytest-split's --splits/--group or --store-durations; pytest-fsplit
rejects those combinations to avoid applying two independent partitions or
recording timings for only one file shard.
Unlike pytest-split's post-collection grouping, pytest-fsplit groups whole files before collection. That means test-order randomization plugins can still reorder items inside the selected files without changing which files belong to a shard.
When nbval is active, .ipynb files are assigned as whole-file shards
automatically. For other file-backed collectors, include those file names with
--fsplit-file-pattern. Pytest-fsplit assigns whole files to shards, so it will
not split one notebook or custom collected file across several groups.
Development
uv sync --extra dev
uv run ruff check .
uv run pytest -q
uv build
Release files for pytest-fsplit 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| pytest_fsplit-0.1.0.tar.gz | 100.2 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| pytest_fsplit-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 122.2 kB
Release files / pytest_fsplit-0.1.0.tar.gz
| Download URL | pytest_fsplit-0.1.0.tar.gz |
|---|---|
| Size | 100.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
861cccd7ca4fa8a64a844e4945c9d49fec4aaa6d77cf376e4a07045bf1a0c494
|
|
BLAKE2b-256 checksum How to use checksums |
4701e81114fa276060bf167635f7b4aca25da93599231bba59c021877de2847e
|
| 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 Aug 20, 2026.
Transparency logRelease files / pytest_fsplit-0.1.0-py3-none-any.whl
| Download URL | pytest_fsplit-0.1.0-py3-none-any.whl |
|---|---|
| Size | 21.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
1609cfc537c0ddbdde84a05f7ed354cd7e64d80ea55cdb911b08b6845da8a3a3
|
|
BLAKE2b-256 checksum How to use checksums |
e04428adcf636653979993b771116a0be80ce973753986a3a3b8373da6843112
|
| 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 Aug 20, 2026.
Transparency log