Skip to content

Commit 227b12e

Browse files
authored
test: speed up pytest runs with xdist (#230)
1 parent 5bf28da commit 227b12e

9 files changed

Lines changed: 221 additions & 71 deletions

File tree

.github/workflows/lint-and-test.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,4 +47,4 @@ jobs:
4747
run: uv sync --all-extras
4848

4949
- name: Run pytest
50-
run: uv run pytest --cov=mitreattack --durations=20
50+
run: uv run --extra dev pytest -n 2 --cov=mitreattack --durations=20

AGENTS.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@
1616
- Before committing, run `just lint`.
1717
- `just lint`: run pre-commit hooks across the repo.
1818
- `just test`: run the pytest suite.
19+
- `just test-xdist`: run the pytest suite in parallel.
1920
- `just test-cov`: run tests with coverage for `mitreattack`.
21+
- `just test-cov-xdist`: run tests with coverage in parallel.
2022
- `just build`: build distributions with `uv build`.
2123
- Without `just`, run the same tools through `uv run ...`.
2224

@@ -32,6 +34,10 @@
3234
- Framework: `pytest` (with `pytest-cov` for coverage checks).
3335
- Place tests under `tests/` and name files/functions `test_*.py` / `test_*`.
3436
- Add or update tests for behavior changes, especially around STIX parsing and changelog/diff output paths.
37+
- Tests that need real ATT&CK STIX data should use the shared STIX fixtures instead of downloading or
38+
preparing bundles directly.
39+
- Parallel runs warm the shared STIX cache before workers start; update `DEFAULT_ATTACK_STIX_PREP` in
40+
`tests/conftest.py` if a new xdist-backed test needs another ATT&CK release.
3541
- Run `just test` locally before opening a PR; use `just test-cov` for larger changes.
3642

3743
## Commit & Pull Request Guidelines

conftest.py

Lines changed: 0 additions & 36 deletions
This file was deleted.

docs/CONTRIBUTING.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,12 +53,19 @@ Run `just` with no arguments to see all available commands. Here are the most co
5353
just lint # Run pre-commit hooks (ruff format) on all files
5454
just test # Run the full test suite, matching CI expectations
5555
just test-fast # Run the fast local subset, excluding integration and slow tests
56+
just test-xdist # Run tests in parallel
5657
just test-cov # Run tests with coverage report
58+
just test-cov-xdist # Run tests with coverage in parallel
5759
just build # Build the package
5860
```
5961

6062
Use `just test-fast` while iterating locally on changes that do not need full STIX-backed export or other slow integration coverage. Tests or setup steps that normally take longer than 10 seconds should be marked `slow`, so they are skipped by `just test-fast`. Before opening a PR, run `just test`; GitHub Actions also runs the full suite with coverage.
6163

64+
Tests that need real ATT&CK STIX data should use the shared STIX fixtures instead of downloading or
65+
preparing bundles directly. Parallel test runs warm the shared STIX cache before workers start; if a
66+
new xdist-backed test needs an additional ATT&CK release, update the cache warmup list in
67+
`tests/conftest.py`.
68+
6269
To run STIX-backed tests against specific local bundles, pass the bundle paths to pytest:
6370

6471
```bash

justfile

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,18 @@ test:
3939
test-fast:
4040
uv run pytest -m "not integration and not slow"
4141

42+
# Run the fast local test subset in parallel
43+
test-fast-xdist workers="auto":
44+
uv run --extra dev pytest -n {{ workers }} -m "not integration and not slow"
45+
46+
# Run tests in parallel
47+
test-xdist workers="auto":
48+
uv run --extra dev pytest -n {{ workers }}
49+
50+
# Run tests with coverage in parallel
51+
test-cov-xdist workers="auto":
52+
uv run --extra dev pytest -n {{ workers }} --cov=mitreattack
53+
4254
# Run tests with coverage
4355
test-cov:
4456
uv run pytest --cov=mitreattack

pyproject.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ dev = [
5959
"pytest>=9.0",
6060
"pytest-cov>=7.0.0",
6161
"pytest-dotenv>=0.5.2",
62+
"pytest-xdist>=3.8.0",
6263
"python-semantic-release>=10.5.0",
6364
"responses>=0.25.8",
6465
"ruff>=0.14.2",
@@ -138,3 +139,7 @@ version_files = [
138139
"docs/conf.py:^release = ['\"](.*)['\"]",
139140
"mitreattack/__init__.py:^__version__ = ['\"](.*)['\"]",
140141
]
142+
143+
[[tool.uv.index]]
144+
url = "https://pypi.org/simple"
145+
default = true

tests/changelog/conftest.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -533,10 +533,10 @@ def golden_161_170_changelog_dir():
533533

534534

535535
@pytest.fixture(scope="session")
536-
def generated_161_170_diffstix(tmp_path_factory) -> DiffStix:
536+
def generated_161_170_diffstix(request) -> DiffStix:
537537
"""Create and cache a DiffStix instance for reuse across tests."""
538538
versions_param = ["16.1", "17.0"]
539-
result_paths = _download_attack_stix_data(versions_param, tmp_path_factory)
539+
result_paths = _download_attack_stix_data(versions_param, config=request.config)
540540
return DiffStix(
541541
domains=["enterprise-attack", "mobile-attack", "ics-attack"],
542542
old=result_paths["16.1"],

0 commit comments

Comments
 (0)