diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 34ee474..79c945c 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -1,7 +1,7 @@ -# This file is autogenerated by maturin v1.3.0 +# This file is autogenerated by maturin v1.4.0 # To update, run # -# maturin generate-ci github +# maturin generate-ci github --pytest # name: CI @@ -9,6 +9,7 @@ on: push: branches: - main + - master tags: - '*' pull_request: @@ -40,6 +41,29 @@ jobs: with: name: wheels path: dist + - name: pytest + if: ${{ startsWith(matrix.target, 'x86_64') }} + shell: bash + run: | + set -e + pip install rebop --find-links dist --force-reinstall + pip install pytest + pytest + - name: pytest + if: ${{ !startsWith(matrix.target, 'x86') && matrix.target != 'ppc64' }} + uses: uraimo/run-on-arch-action@v2.5.0 + with: + arch: ${{ matrix.target }} + distro: ubuntu22.04 + githubToken: ${{ github.token }} + install: | + apt-get update + apt-get install -y --no-install-recommends python3 python3-pip + pip3 install -U pip pytest + run: | + set -e + pip3 install rebop --find-links dist --force-reinstall + pytest windows: runs-on: windows-latest @@ -63,6 +87,14 @@ jobs: with: name: wheels path: dist + - name: pytest + if: ${{ !startsWith(matrix.target, 'aarch64') }} + shell: bash + run: | + set -e + pip install rebop --find-links dist --force-reinstall + pip install pytest + pytest macos: runs-on: macos-latest @@ -85,6 +117,14 @@ jobs: with: name: wheels path: dist + - name: pytest + if: ${{ !startsWith(matrix.target, 'aarch64') }} + shell: bash + run: | + set -e + pip install rebop --find-links dist --force-reinstall + pip install pytest + pytest sdist: runs-on: ubuntu-latest diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 62312cf..b49cc0b 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -12,6 +12,8 @@ repos: - id: end-of-file-fixer - id: trailing-whitespace - id: mixed-line-ending + - id: name-tests-test + args: [--pytest-test-first] - repo: https://github.com/crate-ci/typos rev: v1.17.2 hooks: diff --git a/pyproject.toml b/pyproject.toml index f6e6f24..c1865c0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -15,6 +15,7 @@ extend-exclude = ["benches/*"] target-version = "py39" [tool.ruff.per-file-ignores] +"tests/test_*.py" = ["D", "S101", "PLR2004", "ANN201"] "examples/*" = ["INP001"] "examples/sir.py" = ["T201"] "python/rebop/__init__.py" = ["D104"] diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..5bec482 --- /dev/null +++ b/tests/__init__.py @@ -0,0 +1 @@ +"""Tests for the python bindings.""" diff --git a/tests/test_rebop.py b/tests/test_rebop.py new file mode 100644 index 0000000..dae3915 --- /dev/null +++ b/tests/test_rebop.py @@ -0,0 +1,36 @@ +import numpy as np +import numpy.testing as npt +import pytest +import rebop +import xarray as xr + + +def sir_model(transmission: float = 1e-4, recovery: float = 0.01) -> rebop.Gillespie: + sir = rebop.Gillespie() + sir.add_reaction(transmission, ["S", "I"], ["I", "I"]) + sir.add_reaction(recovery, ["I"], ["R"]) + return sir + + +@pytest.mark.parametrize("seed", [None, *range(10)]) +def test_sir(seed: int): + sir = sir_model() + ds = sir.run({"S": 999, "I": 1}, tmax=250, nb_steps=250, seed=seed) + assert isinstance(ds, xr.Dataset) + npt.assert_array_equal(ds.time, np.arange(251)) + assert all(ds.S >= 0) + assert all(ds.I >= 0) + assert all(ds.R >= 0) + assert all(ds.S <= 1000) + assert all(ds.I <= 1000) + assert all(ds.R <= 1000) + npt.assert_array_equal(ds.S + ds.I + ds.R, [1000] * 251) + + +def test_fixed_seed(): + sir = sir_model() + ds = sir.run({"S": 999, "I": 1}, tmax=250, nb_steps=250, seed=42) + + assert ds.S[-1] == 0 + assert ds.I[-1] == 166 + assert ds.R[-1] == 834