pytest-portion
Select a portion of the collected tests, so you can run different parts of your test suite in different instances to scale horizontally.
Use case
Suppose you have a big, slow test suite, but you can trigger several CI workers to run different portions of it, in a sake lazy/simple way to parallelize it.
A basic, obvious way to do that is to explictily collect from different directories/modules:
- worker1:
pytest tests/a(100 tests, ~4 minutes to finish) - worker2:
pytest tests/b(20 tests, ~1 minute to finish) - worker3:
pytest tests/c tests/d(30 tests, ~1 minute to finish)
The problem is that directory tests/a may have a lot more tests that tests/c plus test/d,
so worker1 takes a lot more to finish.
With pytest-portion you can still split the tests in different instances, but letting
the extension makes the selection in a more balanced way.
- worker1:
pytest --portion 1/3 tests(first 50 tests, ~2 minutes) - worker2:
pytest --portion 2/3 tests(next 50 tests, ~2 minutes) - worker3:
pytest --portion 3/3 tests(last 50 tests, ~2 minutes)
In this case, the tests of all the directories are collected, but only a third (a different one!) of them will be actually executed on each worker.
Note this balance is by number of tests, so if there is very slow tests in a particular portion, the duration may not be expected.
For a fine tuning, you could pass the portion in a more explicit way:
- worker1:
pytest --portion 0:0.5 tests(first half, 1st to 75th test) - worker2:
pytest --portion 0.5:0.8 tests(next 30%, from 76th to 125th) - worker3:
pytest --portion 0.8:1 tests(last 20%)
Installation
You can add "pytest-portion" to your project from PyPI with uv.
uv add --dev pytetest-portion
Or via pip
pip install pytest-portion
Usage
There are three modes of operation: Test-level (default), File-level, and Function-level.
1. Test-level Slicing (Default)
Pytest collects all tests first, then pytest-portion filters them.
Pass --portion <i/n> where:
nis the total number of portions.iis the i-th portion to select (1 <= i <= n).
Note: If the number of tests collected is not divisible by
n, the last portion will contain the rest. For instance, if you havetest_1,test_2andtest_3,--portion 1/2will run the first one, and--portion 2/2the last 2.
Alternatively, use --portion start:end where start and end are coefficients between 0 and 1.
2. File-level Slicing
For very large projects, collection itself can be slow. Use --portion-files to slice the list of
discovered files before pytest starts collecting tests from within them. This can significantly
reduce collection time in large repositories.
# Collect and run only the files belonging to the first half of the suite
pytest --portion 1/2 --portion-files tests/
3. Function-level Slicing
With multiple parametrized test functions (e.g. test_compare1[...], test_compare2[...]), the default splits the entire collected list. That can put all of one function in portion 1 and all of another in portion 2, so workers get uneven loads.
Use --portion-functions to split within each test function instead: each function’s cases are portioned separately, so every function contributes proportionally to the selected set.
# Half from test_compare1 and half from test_compare2
pytest --portion 1/2 --portion-functions tests/
Note:
--portion-filesand--portion-functionscannot be used together.
Contributing
Contributions are very welcome. Please ensure the coverage at least stays the same before you submit a pull request.
License
Distributed under the terms of the BSD-3 license, "pytest-portion" is free and open source software.
Issues
If you encounter any problems, please file an issue along with a detailed description.
Acknowledgements
I used cookiecutter along with @hackebrot's cookiecutter-pytest-plugin template for the boilerplate code of this package. Thanks!
Metadata
Release files for pytest-portion 0.3.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 | Provenance | Actions |
|---|---|---|---|---|
| pytest_portion-0.3.0.tar.gz | 60.6 kB | Without provenance | Details for pytest_portion-0.3.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| pytest_portion-0.3.0-py3-none-any.whl | Python 3 | none | any | Details for pytest_portion-0.3.0-py3-none-any.whl |
Total release size: 68.2 kB
Release files / pytest_portion-0.3.0.tar.gz
| Download URL | pytest_portion-0.3.0.tar.gz |
|---|---|
| Size | 60.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
a1e7e8bd01fa8146bb33faff2030075546ee3be131c8573b4ad0aaaff43f2001
|
|
BLAKE2b-256 checksum How to use checksums |
202c7635034c170f1379ce47ab69a56cc2bd7f3d930c80ae1210be92eea5bcb7
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.10.8 {"installer":{"name":"uv","version":"0.10.8","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / pytest_portion-0.3.0-py3-none-any.whl
| Download URL | pytest_portion-0.3.0-py3-none-any.whl |
|---|---|
| Size | 7.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
020fb36dce7f0f52f5765cacec7bac34759492aece67f55fa3a50d4e110192b6
|
|
BLAKE2b-256 checksum How to use checksums |
98f41b2e017a5b6fd499451235f4c9eddc5aaf357e39949ddd7f336aec2546a8
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.10.8 {"installer":{"name":"uv","version":"0.10.8","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Security for pytest-portion 0.3.0
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.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.