diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml index 96aaa0c..c3cdb43 100644 --- a/.github/workflows/pr.yaml +++ b/.github/workflows/pr.yaml @@ -7,6 +7,13 @@ concurrency: group: pr-${{ github.ref }} cancel-in-progress: true +env: + OMP_NUM_THREADS: 1 + MKL_NUM_THREADS: 1 + OPENBLAS_NUM_THREADS: 1 + NUMEXPR_NUM_THREADS: 1 + PYTHONHASHSEED: 0 + jobs: unit: name: Unit @@ -34,7 +41,7 @@ jobs: python -m pip install -e .[testing] - name: Pytest (unit) • ${{ matrix.os }}, ${{ matrix.python-version }} - run: python -m pytest tests/unit + run: python -m pytest tests/unit --cache-clear discover-systems: name: Discover regression systems @@ -81,29 +88,30 @@ jobs: - name: Set up Python 3.14 uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 with: - python-version: "3.14" + python-version: "3.13" cache: pip - - name: Cache testdata - uses: actions/cache@v4 - with: - path: .testdata - key: codeentropy-testdata-${{ runner.os }}-py314 - - name: Install testing dependencies run: | python -m pip install --upgrade pip python -m pip install -e .[testing] + - name: Clean local test caches + shell: bash + run: | + rm -rf .pytest_cache + find . -type d -name "__pycache__" -prune -exec rm -rf {} + + - name: Run fast regression tests (per system) run: | python -m pytest tests/regression \ -m "not slow" \ - -n auto \ - --dist=loadscope \ - -k "${{ matrix.system }}" \ + --cache-clear \ + -n 1 \ + --system "${{ matrix.system }}" \ -vv \ - --durations=20 + --durations=20 \ + --codeentropy-debug - name: Upload artifacts (failure) if: failure() @@ -200,6 +208,7 @@ jobs: - name: Run coverage run: | pytest tests/unit \ + --cache-clear \ --cov CodeEntropy \ --cov-report term-missing \ --cov-report xml \ diff --git a/tests/regression/conftest.py b/tests/regression/conftest.py index 2dfd281..45f5635 100644 --- a/tests/regression/conftest.py +++ b/tests/regression/conftest.py @@ -1,6 +1,5 @@ from __future__ import annotations -import os import random import numpy as np @@ -48,8 +47,6 @@ def pytest_configure(config: pytest.Config) -> None: random.seed(seed) np.random.seed(seed) - os.environ["PYTHONHASHSEED"] = "0" - def pytest_collection_modifyitems( config: pytest.Config, items: list[pytest.Item] diff --git a/tests/regression/prepare_testdata.py b/tests/regression/prepare_testdata.py new file mode 100644 index 0000000..76df4c1 --- /dev/null +++ b/tests/regression/prepare_testdata.py @@ -0,0 +1,64 @@ +from __future__ import annotations + +import argparse +from pathlib import Path +from typing import Any + +import yaml + +from tests.regression.cases import discover_cases +from tests.regression.helpers import ( + _abspathify_config_paths, + ensure_testdata_for_system, +) + + +def unwrap_case(case_or_param: Any) -> Any: + if hasattr(case_or_param, "values"): + values = case_or_param.values + if values: + return values[0] + return case_or_param + + +def required_paths_for_case(case: Any) -> list[Path]: + raw = yaml.safe_load(case.config_path.read_text()) + cooked = _abspathify_config_paths(raw, base_dir=case.config_path.parent) + + required: list[Path] = [] + run1 = cooked.get("run1") + + if isinstance(run1, dict): + ff = run1.get("force_file") + if isinstance(ff, str) and ff: + required.append(Path(ff)) + + for p in run1.get("top_traj_file") or []: + if isinstance(p, str) and p: + required.append(Path(p)) + + return required + + +def main() -> None: + parser = argparse.ArgumentParser() + parser.add_argument("--system", action="append", default=None) + args = parser.parse_args() + + selected = set(args.system or []) + + for case_or_param in discover_cases(): + case = unwrap_case(case_or_param) + + if selected and case.system not in selected: + continue + + required = required_paths_for_case(case) + if required: + ensure_testdata_for_system(case.system, required_paths=required) + + print("Regression test data prepared.") + + +if __name__ == "__main__": + main()