A pytest plugin to split your test suite into multiple parts
Project description
pytest-cdist
Like pytest-xdist, but for distributed environments - pytest-cdist allows to split a test suite into multiple parts and run them independently.
This is a work in progress
Why?
pytest-xdist can help to parallelize test execution, as long as you can scale horizontally. In many environments, such as GitHub actions with GitHub runners, this is only possible to a fairly limited degree, which can be an issue if your test suite grows large. pytest-cdist can help with this by allowing to execute individual chunks of your test suite in a deterministic order, so you can use multiple concurrent jobs to run each individual chunk.
How?
pytest --cdist-group=1/2 # will run the first half of the test suite
pytest --cdist-group=2/2 # will run the second half of the test suite
In a GitHub workflow
jobs:
test:
runs-on: ubuntu-latest
matrix:
strategy:
cdist-groups: [1, 2, 3, 4]
steps:
- uses: actions/checkout@v4
# set up environment here
- name: Run pytest
run: pytest --cdist-group=${{ matrix.cdist-group }}/4
Usage
Configuration
Pytest-cdist comes with several CLI and pytest-ini options:
| CLI | Ini | Allowed values | Default |
|---|---|---|---|
--cdist-justify-items |
cdist-justify-items |
none, file, scope |
none |
--cdist-group-steal |
--cdist-group-steal |
<target group>:<percentage> / <target group>:<percentage>:<source group> |
- |
--cdist-report |
- | - | false |
--cdist-report-dir |
cdist-report-dir |
. |
Controlling how items are split up
By default, pytest-cdist will split up the items into groups as evenly as possible. Sometimes this may not be desired, for example if there's some costly fixtures requested by multiple tests, which should ideally only run once.
To solve this, the cdist-justify-items option can be used to configure how items are
split up. It can take two possible values:
file: Ensure all items inside a file end up in the same groupscope: Ensure all items in the same pytest scope end up in the same group
[pytest]
cdist-justify-items=file
pytest --cdist-group=1/2 --cdist-justify-items=file
Skewing the group sizes
Normally, items are distributed evenly among groups, which is a good default, but there may be cases where this will result in an uneven execution time, if one group contains a number of slower tests than the other ones.
To work around this, the cdist-group-steal option can be used. It allows to specific
a certain percentage of items a group will "steal" from other groups. For example
--cdist-group-steal=2:30 will cause group 2 to steal 30% of items from all other
groups.
[pytest]
cdist-group-steal=2:30
pytest --cdist-group=1/2 --cdist-group-steal=2:30
It is also possible to redistribute items between two specific groups, by specifying both as source and a target group. The following configuration would assign 50% of the items in group 1 to group 2:
pytest --cdist-group=1/3 --cdist-group-steal=1:50:2
With pytest-xdist
When running under pytest-xdist, pytest-cdist will honour tests marked with
xdist_group, and group them together in the same cdist group.
With pytest-randomly
To use pytest-cdist with pytest-randomly's test reordering, a randomness seed that's consistent across the different pytest invocations needs to be specified, otherwise, test cases would be dropped, since pytest-cdist has to rely on a consistent collection order to split test cases among its groups.
To achieve this, a random source such as the current timestamp can be used:
jobs:
setup_randomly_seed:
runs-on: ubuntu-latest
outputs:
randomly_seed: ${{ steps.set-seed.outputs.randomly_seed }}
steps:
- name: Set seed
id: set-seed
run: echo "randomly_seed=$(date +%s)" >> $GITHUB_OUTPUT
test:
runs-on: ubuntu-latest
needs: setup_randomly_seed
matrix:
strategy:
cdist-groups: [1, 2, 3, 4]
steps:
- uses: actions/checkout@v4
- name: Run pytest
run: >
pytest
--cdist-group=${{ matrix.cdist-group }}/4
--randomly-seed=${{ needs.setup_randomly_seeds.outputs.randomly_seed }}
or a bit simpler (but less random), using the current git hash:
jobs:
test:
runs-on: ubuntu-latest
needs: setup_randomly_seed
matrix:
strategy:
cdist-groups: [1, 2, 3, 4]
steps:
- uses: actions/checkout@v4
- name: Run pytest
run: >
pytest
--cdist-group=${{ matrix.cdist-group }}/4
--randomly-seed=$((16#$(git rev-parse HEAD)))
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
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pytest_cdist-0.5.1.tar.gz.
File metadata
- Download URL: pytest_cdist-0.5.1.tar.gz
- Upload date:
- Size: 31.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ce398283b2e2557dc1d965f482286bc3950532ad58ccb18822c4e84eebf44139
|
|
| MD5 |
22605ccd9d15adac6272def76a4b44fa
|
|
| BLAKE2b-256 |
fcb1e2f7fe97dcc7d4f15b7b68539c0d3197db4e07e21a040684775a501dcfc5
|
Provenance
The following attestation bundles were made for pytest_cdist-0.5.1.tar.gz:
Publisher:
publish.yaml on provinzkraut/pytest-cdist
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pytest_cdist-0.5.1.tar.gz -
Subject digest:
ce398283b2e2557dc1d965f482286bc3950532ad58ccb18822c4e84eebf44139 - Sigstore transparency entry: 804985653
- Sigstore integration time:
-
Permalink:
provinzkraut/pytest-cdist@849648b441aebb258205f7150fe7a3a5b31efe2b -
Branch / Tag:
refs/tags/v0.5.1 - Owner: https://github.com/provinzkraut
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yaml@849648b441aebb258205f7150fe7a3a5b31efe2b -
Trigger Event:
release
-
Statement type:
File details
Details for the file pytest_cdist-0.5.1-py3-none-any.whl.
File metadata
- Download URL: pytest_cdist-0.5.1-py3-none-any.whl
- Upload date:
- Size: 8.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b1bcabd1948c20dbf98ff4c98eeae391dbdf14e97eae8617e8d0d1e023d3cf32
|
|
| MD5 |
a813069aa658ccf47cf421e80d629ae6
|
|
| BLAKE2b-256 |
e0ea2494a44e02263a35905446fcafcc0edca4bedfc72e9654dc84304ee11f69
|
Provenance
The following attestation bundles were made for pytest_cdist-0.5.1-py3-none-any.whl:
Publisher:
publish.yaml on provinzkraut/pytest-cdist
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pytest_cdist-0.5.1-py3-none-any.whl -
Subject digest:
b1bcabd1948c20dbf98ff4c98eeae391dbdf14e97eae8617e8d0d1e023d3cf32 - Sigstore transparency entry: 804985659
- Sigstore integration time:
-
Permalink:
provinzkraut/pytest-cdist@849648b441aebb258205f7150fe7a3a5b31efe2b -
Branch / Tag:
refs/tags/v0.5.1 - Owner: https://github.com/provinzkraut
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yaml@849648b441aebb258205f7150fe7a3a5b31efe2b -
Trigger Event:
release
-
Statement type: