Skip to content

Merge pull request #1021 from lanl/fix/tests-follow-bngsim-017-atol #885

Merge pull request #1021 from lanl/fix/tests-follow-bngsim-017-atol

Merge pull request #1021 from lanl/fix/tests-follow-bngsim-017-atol #885

Workflow file for this run

name: tests
on:
push:
branches: [main]
pull_request:
jobs:
pytest:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
# Every supported version (requires-python >= 3.12; classifiers list
# through 3.14). CI is free on this public repo, so we test each claimed
# version rather than just the endpoints. 3.11 left with the petab 0.9
# floor (#591): petab 0.9.0 requires >= 3.12.
include:
- python-version: '3.12'
- python-version: '3.13'
# bngsim publishes cp310-cp313 wheels, so 3.14 would fall back to
# building the sdist (C++17 toolchain, CMake >= 3.20, Ninja) inside
# the pytest job. Keep this leg deliberately bngsim-less instead: it
# is the guard that the bngsim-free code paths still work (a bare
# `pip install pybnf` on a machine with no wheel), which is worth a
# leg of its own regardless. Drop `no-bngsim` here the day a cp314
# wheel ships.
- python-version: '3.14'
no-bngsim: '1'
name: pytest (py${{ matrix.python-version }}${{ matrix.no-bngsim == '1' && ', bngsim-less' || '' }})
steps:
- uses: actions/checkout@v6
- uses: ./.github/actions/setup-pybnf
with:
python-version: ${{ matrix.python-version }}
bngsim: ${{ matrix.no-bngsim == '1' && 'false' || 'true' }}
- name: Warm the arviz version-check stamp
# arviz < 1.0 prints a daily refactor warning on import and
# records the date through a helper it calls atomic, which it is not: the temp file has
# a FIXED name, `daily_warning.tmp`, so every process shares it.
#
# tmp = path.with_suffix(path.suffix + ".tmp")
# tmp.write_text(text)
# tmp.replace(path)
#
# Under `-n auto` the xdist workers import arviz at once, the first replace() renames
# the shared temp away, and the rest raise FileNotFoundError -- which surfaces as
# test_inference_data.py failing to collect on some workers but not others, i.e.
# "Different tests were collected between gw0 and gw1", not as an arviz error.
#
# Importing once here, serially, writes today's date so arviz's own `last_date != today`
# guard short-circuits in every worker and the racing write never happens. Tolerant of
# arviz being absent (the bngsim-less leg resolves a different set) and of arviz >= 1.0,
# which dropped the stamp entirely.
run: |
uv run --no-sync python -c "
try:
import arviz # noqa: F401
except ImportError:
pass
"
- name: Run unit tests (parallel)
env:
# Empty except on the bngsim-less leg, where it is '1'. An empty value
# reads as unset (pybnf/_bngsim_caps.py tests truthiness), so bngsim
# is imported and the bngsim/nfsim/rulemonkey/sbml/antimony-marked
# tests run for real; with '1' conftest.py auto-skips them.
PYBNF_NO_BNGSIM: ${{ matrix.no-bngsim }}
# -m: the default addopts expression is `not slow and not recovery`, and
# naming -m here REPLACES it -- so both tiers must be restated. Omitting
# `not recovery` used to be harmless because 129 of the 130 recovery
# tests skip without bngsim; with bngsim installed they are real
# parameter-recovery fits through the backend and the job would run for
# over an hour. (The cost of deselecting: the 130th, a roadrunner-backed
# Boehm oracle in test_petab_sbml_layer.py, is bngsim-free and no longer
# runs here.) -n auto parallelizes across the runner's cores.
#
# --no-sync: do NOT let `uv run` re-resolve the project env from
# pyproject.toml -- the composite action already populated .venv with an
# exact dependency set (and on the bngsim-less leg a re-resolve would
# pull bngsim right back in).
run: uv run --no-sync pytest -m "not slow and not recovery" -n auto
# The gradient path (ADR-0059): the HMC reference sampler and the jax-gated
# gradient-assembly tests need the optional pybnf[jax] extra (jax + jaxlib +
# blackjax). jaxlib is a large install relative to the rest of the dep set, so
# rather than pay it on all four matrix legs above this one dedicated job turns
# the `jax` input on and runs exactly the two files that exercise the gradient
# path: tests/test_hmc.py (the whole ADR-0059 HMC oracle, skipif-gated on the
# extra) and tests/test_gradient_assembly.py (its jax tests importorskip). Those
# gradient tests include the fd-acceptance-gate cases, which are ALSO
# bngsim-marked -- they check the analytic jax gradient against a
# finite-difference through a real bngsim model -- so this leg keeps bngsim
# installed (the default) and PYBNF_NO_BNGSIM unset. One Python version is
# enough: the oracle is about numerical correctness, not version-compat. Before
# this job, tests/test_hmc.py had never run on a hosted runner (#516).
pytest-jax:
runs-on: ubuntu-latest
name: pytest (jax / HMC)
steps:
- uses: actions/checkout@v6
- uses: ./.github/actions/setup-pybnf
with:
python-version: '3.12'
jax: 'true'
# This job also runs 3.12 through setup-pybnf, so give it its own cache
# namespace to avoid racing the matrix py3.12 job's save (see the
# cache-suffix input).
cache-suffix: pybnf-jax
- name: Run the HMC + jax gradient tests
# Deselect slow/recovery exactly as the matrix legs do (the one slow HMC
# cross-check in test_hmc.py stays out of the default run). -n auto
# parallelizes across the runner's cores.
run: uv run --no-sync pytest -m "not slow and not recovery" tests/test_hmc.py tests/test_gradient_assembly.py -n auto