A pytest plugin that selectively runs tests impacted by code changes via git introspection, AST parsing, and dependency graph analysis.
Project description
pytest-impacted
Run only the tests that matter. A pytest plugin that uses git diff, AST parsing, and dependency graph analysis to selectively run tests impacted by your code changes.
pytest --impacted --impacted-module=my_package # unstaged changes
pytest --impacted --impacted-module=my_package \
--impacted-git-mode=branch \
--impacted-base-branch=main # branch changes vs main
Key Features
| Feature | Details | |
|---|---|---|
| :zap: | Fast feedback | Only runs tests affected by your changes — skip the rest |
| :deciduous_tree: | Dependency-aware | Follows import chains transitively, not just direct file changes |
| :gear: | No imports at analysis time | Filesystem discovery + AST parsing — no module-level side effects |
| :test_tube: | pytest-native | Works as a standard pytest plugin with familiar CLI options |
| :wrench: | conftest.py aware | Changes to conftest.py automatically impact all tests in scope |
| :building_construction: | CI-friendly | Standalone impacted-tests CLI for two-stage CI pipelines |
| :shield: | Helpful errors | Validates config early with clear messages and suggestions |
[!CAUTION] This project is currently in beta. Please report bugs via the Issues tab.
Installation
pip install pytest-impacted
Or with uv:
uv add pytest-impacted
Requires Python 3.11+.
Quick Start
1. Run tests impacted by uncommitted changes:
pytest --impacted --impacted-module=my_package
2. Run tests impacted by branch changes (vs main):
pytest --impacted \
--impacted-module=my_package \
--impacted-git-mode=branch \
--impacted-base-branch=main
3. Include tests outside the package directory:
pytest --impacted \
--impacted-module=my_package \
--impacted-tests-dir=tests
That's it. Unaffected tests are automatically skipped.
How It Works
Git diff → Changed files → Module resolution → AST import parsing → Dependency graph → Impacted tests
- Git introspection identifies which files changed (unstaged edits or branch diff)
- Filesystem discovery maps file paths to Python module names — without importing anything
- AST parsing (via astroid) extracts import relationships from source files
- Dependency graph (via NetworkX) traces transitive dependencies from changed modules to test modules
- Test filtering skips tests whose modules are not in the impact set
The philosophy is to err on the side of caution: we favor false positives (running a test that didn't need to run) over false negatives (missing a test that should have run).
Usage
Git Modes
| Mode | Flag | What it compares |
|---|---|---|
| unstaged (default) | --impacted-git-mode=unstaged |
Working directory changes + untracked files |
| branch | --impacted-git-mode=branch |
All commits on current branch vs base branch |
The --impacted-base-branch flag accepts any valid git ref, including expressions like HEAD~4.
External Tests Directory
When your tests live outside the namespace package (a common layout), use --impacted-tests-dir so the dependency graph includes them:
pytest --impacted \
--impacted-module=my_package \
--impacted-tests-dir=tests
CI Integration
For CI pipelines where git access and test execution happen in separate stages, use the impacted-tests CLI to generate the test file list:
# Stage 1: identify impacted tests
impacted-tests --module=my_package --git-mode=branch --base-branch=main > impacted_tests.txt
# Stage 2: run only those tests
pytest $(cat impacted_tests.txt)
Configuration via pyproject.toml
All CLI options can be set as defaults in your pyproject.toml (or pytest.ini):
[tool.pytest.ini_options]
impacted = true
impacted_module = "my_package"
impacted_git_mode = "branch"
impacted_base_branch = "main"
impacted_tests_dir = "tests"
CLI flags override these defaults.
All Options
| Option | Default | Description |
|---|---|---|
--impacted |
false |
Enable the plugin |
--impacted-module |
(required) | Top-level Python package to analyze |
--impacted-git-mode |
unstaged |
Git comparison mode: unstaged or branch |
--impacted-base-branch |
(required for branch mode) | Base branch/ref for branch-mode comparison |
--impacted-tests-dir |
None |
Directory containing tests outside the package |
Alternatives
| Project | Notes |
|---|---|
| pytest-testmon | Most popular option. Uses coverage-based granular change tracking. More precise but heavier; may conflict with other plugins. |
| pytest-picked | Runs tests from directly modified files only — no transitive dependency analysis. |
| pytest-affected | Appears unmaintained, no source repository. |
Development
This project uses uv for dependency management.
# Setup
uv sync --all-extras --dev
# Run tests
uv run python -m pytest
# Run tests with coverage
uv run python -m pytest --cov=pytest_impacted --cov-branch tests
# Lint + format + type check
pre-commit run --all-files
License
Project details
Release history Release notifications | RSS feed
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_impacted-0.16.1.tar.gz.
File metadata
- Download URL: pytest_impacted-0.16.1.tar.gz
- Upload date:
- Size: 656.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8cee6d57c8ee06f0a97d8d891b83aeb4772cb4b952a31a36c822ac3426de6195
|
|
| MD5 |
280b04f374d7d39c92649848b70c9355
|
|
| BLAKE2b-256 |
ad224bd96331711a80cc51eae4e859627715260b77849dd82aa7a63cc7b9d384
|
Provenance
The following attestation bundles were made for pytest_impacted-0.16.1.tar.gz:
Publisher:
publish-to-pypi.yml on promptromp/pytest-impacted
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pytest_impacted-0.16.1.tar.gz -
Subject digest:
8cee6d57c8ee06f0a97d8d891b83aeb4772cb4b952a31a36c822ac3426de6195 - Sigstore transparency entry: 945194389
- Sigstore integration time:
-
Permalink:
promptromp/pytest-impacted@c5149088a1b4574ba75173f3ccec1f2263f7490f -
Branch / Tag:
refs/tags/0.16.1 - Owner: https://github.com/promptromp
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-to-pypi.yml@c5149088a1b4574ba75173f3ccec1f2263f7490f -
Trigger Event:
push
-
Statement type:
File details
Details for the file pytest_impacted-0.16.1-py3-none-any.whl.
File metadata
- Download URL: pytest_impacted-0.16.1-py3-none-any.whl
- Upload date:
- Size: 21.7 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 |
ca619fb1a041f868bcf8c0fc5d189825869d075139320babd7066440a5b5cd0a
|
|
| MD5 |
08ae0be4aef0a0af17f6c4084b03121e
|
|
| BLAKE2b-256 |
bf348e5ffb93308ca75875d7bbfe37b2791f42f2a25a1b19c35ef81d2d85c89f
|
Provenance
The following attestation bundles were made for pytest_impacted-0.16.1-py3-none-any.whl:
Publisher:
publish-to-pypi.yml on promptromp/pytest-impacted
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pytest_impacted-0.16.1-py3-none-any.whl -
Subject digest:
ca619fb1a041f868bcf8c0fc5d189825869d075139320babd7066440a5b5cd0a - Sigstore transparency entry: 945194442
- Sigstore integration time:
-
Permalink:
promptromp/pytest-impacted@c5149088a1b4574ba75173f3ccec1f2263f7490f -
Branch / Tag:
refs/tags/0.16.1 - Owner: https://github.com/promptromp
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-to-pypi.yml@c5149088a1b4574ba75173f3ccec1f2263f7490f -
Trigger Event:
push
-
Statement type: