pytest-xdist
The pytest-xdist plugin extends pytest with new test execution modes, primarily designed for distributing tests across multiple CPUs or hosts to significantly speed up test execution. It also offers features like running tests in a Python subprocess and formerly supported remote SSH execution and `--looponfail` mode. Currently at version 3.8.0, the library is actively maintained with regular feature updates and bug fixes.
Warnings
- gotcha The `-s` or `--capture=no` option for disabling pytest's output capture does not work with `pytest-xdist`. This means you will not see real-time stdout/stderr output from workers, and debugging with tools like `PDB` is generally not supported for tests running in parallel workers.
- gotcha Tests using `pytest.mark.parametrize` with unordered iterables (e.g., `set`) can lead to inconsistent test collection order across workers, causing `pytest-xdist` to fail.
- deprecated The `--looponfail` and `--rsyncdir` command-line arguments and their corresponding configuration variables (`looponfailroots`, `rsyncdirs`) are deprecated. They are scheduled for removal in `pytest-xdist 4.0`.
- gotcha pytest's `scope='session'` fixtures are executed once per *worker process*, not once for the entire `pytest-xdist` run across all workers. This can lead to unexpected resource setup/teardown behavior and state issues if not managed carefully.
- breaking Users have reported that `--exitfirst` (`-x`) (which stops the test session on the first failure) does not function as expected with `pytest-xdist` versions 3.4.0 and higher. Tests might continue running in other workers despite a failure.
Install
-
pip install pytest-xdist -
pip install pytest-xdist[psutil]
Imports
- pytest-xdist
pytest -n auto
Quickstart
# Assuming you have pytest and pytest-xdist installed and tests in a 'tests/' directory
# Create a simple test file, e.g., tests/test_example.py
# import time
# def test_fast():
# assert True
# def test_medium():
# time.sleep(0.5)
# assert True
# def test_slow():
# time.sleep(1)
# assert True
import os
import subprocess
def run_pytest_xdist(num_processes):
cmd = ['pytest', '-n', str(num_processes)]
print(f"Running: {' '.join(cmd)}")
result = subprocess.run(cmd, capture_output=True, text=True)
print(result.stdout)
if result.stderr:
print("STDERR:", result.stderr)
return result.returncode
# Example usage: run tests on all available CPU cores
# A real-world scenario would just be `pytest -n auto` from the command line
if __name__ == '__main__':
# Ensure pytest is installed for this example to run locally in a script
try:
import pytest
except ImportError:
print("pytest is not installed. Please install with 'pip install pytest'.")
exit(1)
print("\n--- Running tests with pytest -n auto ---")
# In a real shell, you would simply type: pytest -n auto
# For programmatic execution, we demonstrate the subprocess call
exit_code = run_pytest_xdist('auto')
if exit_code == 0:
print("Tests passed successfully with -n auto.")
else:
print(f"Tests failed with -n auto. Exit code: {exit_code}")
print("\n--- Running tests with pytest -n 2 ---")
# In a real shell, you would simply type: pytest -n 2
exit_code = run_pytest_xdist(2)
if exit_code == 0:
print("Tests passed successfully with -n 2.")
else:
print(f"Tests failed with -n 2. Exit code: {exit_code}")