Skip to main content

mpi-pytest

Pytest plugin that lets you run tests in parallel with MPI.

mpi-pytest provides:

  • A parallel marker indicating that the test must be run under MPI.
  • A parallel_assert function for evaluating assertions in a deadlock-safe way.

parallel marker

Writing a parallel test simply requires marking the test with the parallel marker:

@pytest.mark.parallel(nprocs=5)  # run in parallel with 5 processes
def test_my_code_on_5_procs():
    ...

@pytest.mark.parallel(5)  # the "nprocs" kwarg is optional
def test_my_code_on_5_procs_again():
    ...

@pytest.mark.parallel  # run in parallel with the default number of processes (3)
def test_my_code_on_3_procs():
    ...

@pytest.mark.parallel()  # the brackets are optional
def test_my_code_on_3_procs_again():
    ...

One can also mark a test with a sequence of values for nprocs:

@pytest.mark.parallel(nprocs=[1, 2, 3])  # run in parallel on 1, 2 and 3 processes
def test_my_code_on_variable_nprocs():
    ...

@pytest.mark.parallel([1, 2, 3])  # again the "nprocs" kwarg is optional
def test_my_code_on_variable_nprocs_again():
    ...

If multiple numbers of processes are requested then the tests are parametrised and renamed to, in this case, test_my_code_on_variable_nprocs[nprocs=1], test_my_code_on_variable_nprocs[nprocs=2] and test_my_code_on_variable_nprocs[nprocs=3].

When running the code with these parallel markers, mpi-pytest adds extra markers to each test to allow one to select all tests with a particular number of processors. For example, to select all parallel tests on 3 processors, one should run:

$ mpiexec -n 3 pytest -m parallel[3]

It is also possible to specify that only tests with a matching level of parallelism to the outer mpiexec call be run. For example:

$ mpiexec -n 3 pytest -m parallel[match]

is equivalent to passing -m parallel[3].

Serial tests - those either unmarked or marked @pytest.mark.parallel(1) - can be selected by running:

$ pytest -m parallel[1]

Forking mode

mpi-pytest can be used in one of two modes: forking or non-forking. The former works as follows:

  1. The user calls pytest (not mpiexec -n <# proc> pytest). This launches the "parent" pytest process.
  2. This parent pytest process collects all the tests and begins to run them.
  3. When a test is found with the parallel marker, rather than executing the function as before, a subprocess is forked calling mpiexec -n <# proc> pytest this_specific_test_file.py::this_specific_test. This produces <# proc> 'child' pytest processes that execute the test together.
  4. If this terminates successfully then the test is considered to have passed.

This is convenient for development for a number of reasons:

  • The plugin composes better with other pytest plugins like pytest-xdist.
  • It is not necessary to wrap pytest invocations with mpiexec calls, and all parallel and serial tests can be run at once.

There are however a number of downsides:

  • Not all MPI distributions support running in this format because it involves nested calls to MPI_Init (as the parent process will often call MPI_Init during import). In particular the OpenMPI packaged with Ubuntu will not run in this mode.
  • Forking a subprocess can be expensive since a completely fresh Python interpreter is launched each time.
  • Sandboxing each test means that polluted global state at the end of a test cannot be detected.

Non-forking mode

With these significant limitations in mind, mpi-pytest therefore also supports a non-forking mode. To use it, one simply needs to wrap the pytest invocation with mpiexec, no additional configuration is necessary. For example, to run all of the parallel tests on 2 ranks one needs to execute:

$ mpiexec -n 2 pytest -m parallel[2]

parallel_assert

Using regular assert statements can be unsafe in parallel codes. Consider the code:

@pytest.mark.parallel(2)
def test_something():
    # this will only fail on *some* ranks
    assert COMM_WORLD.rank == 0

    # this will hang
    COMM_WORLD.barrier()

One can see that failing assertions on some ranks but not others will violate SPMD and lead to deadlocks. To avoid this, mpi-pytest provides a parallel_assert function used as follows:

from pytest_mpi import parallel_assert

@pytest.mark.parallel(2)
def test_something():
    # this will fail on *all* ranks
    parallel_assert(COMM_WORLD.rank == 0)
    ...

Configuration

mpi-pytest respects the environment variable PYTEST_MPI_MAX_NPROCS, which defines the maximum number of processes that can be requested by a parallel marker. If this value is exceeded an error will be raised.

Copyright

Copyright (C) 2025 Imperial College London and others

mpi-pytest is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

mpi-pytest is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License along with mpi-pytest. If not, see https://www.gnu.org/licenses/.

Metadata

Release files for mpi-pytest 2026.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for mpi-pytest 2026.0
File Size Uploaded Provenance
mpi_pytest-2026.0.tar.gz 11.1 kB With provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for mpi-pytest 2026.0
File Interpreter ABI Platform
mpi_pytest-2026.0-py3-none-any.whl Python 3 none any Details

Total release size: 22.8 kB

Release files / mpi_pytest-2026.0.tar.gz

Download URL mpi_pytest-2026.0.tar.gz
Size 11.1 kB
Tags Source
SHA-256 checksum
How to use checksums
f7d0e9077cee8a8ecffaef51c2f2f1a7783a58513714d757779cfd687455cb01
BLAKE2b-256 checksum
How to use checksums
1256bef4ddf702cf7d8131450244b8eb391079d269a4050d4b13da012f9efdf1
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

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 Feb 10, 2026.

Transparency log

Release files / mpi_pytest-2026.0-py3-none-any.whl

Download URL mpi_pytest-2026.0-py3-none-any.whl
Size 11.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
6949cb59616ce168957303f6bc367f47f289bea18b9cec267464ff8ebf919a83
BLAKE2b-256 checksum
How to use checksums
6748c66c6eb5ca34774bded2237671c3019b86b544697de3660c1f9418779a32
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

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 Feb 10, 2026.

Transparency log

Security for mpi-pytest 2026.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.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for mpi_pytest-2026.0.tar.gz

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 Feb 10, 2026.

Transparency log

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.

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