Development & Testing¶
This page describes how to set up a development environment for OpenSpliceAI and how to run its test suite and quality-control tooling. It is intended for contributors and for anyone who wants to verify a local change before opening a pull request.
Installing the development dependencies¶
Install OpenSpliceAI in editable mode together with the optional dev extra. This pulls in
the test runner, linter, pre-commit, and coverage tooling on top of the runtime requirements:
pip install -e '.[dev]'
The dev extra installs pytest (test runner), pytest-cov (coverage), ruff
(linter), and pre-commit (git hooks). A lighter test extra is also available
(pip install -e '.[test]') if you only need pytest and pytest-cov.
Note
tensorflow / keras are not part of the dev extra. They are only required for
the small set of Keras-specific tests (and for scoring with the original Keras SpliceAI
models in the variant subcommand). Tests that need them are auto-skipped when the
packages are absent.
Running the test suite¶
The suite lives under tests/ and contains 143 tests (collected via
pytest --collect-only). It is designed to run CPU-only so it can execute on any
machine, including CI runners without a GPU.
Run the full suite from the repository root:
pytest
For a fast inner-loop run, deselect the heavier end-to-end and long-running tests using the markers (see below):
# Fast: skip end-to-end integration and slow tests
pytest -m "not integration and not slow"
# Full: everything, including the tiny end-to-end flows
pytest
You can also scope the run to a single layer or file:
pytest tests/unit # unit tests only
pytest tests/integration # end-to-end smoke tests only
pytest tests/unit/test_variant_utils.py
Test markers¶
Markers are declared in pytest.ini and enforced with --strict-markers (an unknown
marker is an error). The available markers are:
Marker |
Meaning |
|---|---|
|
End-to-end flow exercised on tiny synthetic fixtures (CPU only). |
|
Long-running test; deselect for a quick inner-loop run. |
|
Requires a CUDA device; skipped on CPU-only machines. |
|
Requires |
Select or deselect markers with -m, e.g. pytest -m integration to run only the
end-to-end flows, or pytest -m "not slow" to skip the long-running tests.
Layout of tests/¶
The suite is organized into three layers plus shared fixtures:
tests/
├── conftest.py # shared pytest fixtures / configuration
├── fixtures/ # synthetic genomes, annotations, and datasets
│ └── synthetic.py
├── unit/ # fast, isolated tests of individual functions
├── integration/ # end-to-end smoke tests on tiny fixtures (CPU)
└── regression/ # guards against previously fixed bugs
unit/ — fast, isolated checks of individual functions and classes (CLI argument parsing, the model forward pass, one-hot encoding utilities, temperature scaling, transfer layer freezing, variant delta-score math, etc.).
integration/ — minimal end-to-end runs of each subcommand (
create-data,train,transfer,calibrate,predict,variant) on the tiny synthetic fixtures, verifying that the pipelines run on CPU and produce the expected output files.regression/ — targeted tests that lock in the behavior of previously fixed bugs (e.g. minus-strand labeling and the
clip_datapointscropping invariant).fixtures/ — synthetic, deterministically generated inputs (a mini genome, GFF annotation, HDF5 datasets, and VCF/variant inputs) so the suite has no large external data dependencies.
Linting with ruff¶
OpenSpliceAI uses ruff for linting, configured in
ruff.toml. The configuration focuses on real correctness issues (pyflakes F checks)
plus basic errors/warnings (E, W); line-length (E501) and ambiguous single-letter
names (E741) are intentionally ignored, and legacy/experimental trees are excluded.
ruff check . # report lint issues
ruff check --fix . # auto-fix what ruff can fix safely
Pre-commit hooks¶
A pre-commit configuration (.pre-commit-config.yaml) runs
ruff (with --fix) and a couple of lightweight hygiene hooks (check-yaml,
check-added-large-files) on every commit. Install the git hook once, then optionally run
it across the whole repository:
pre-commit install # install the git hook
pre-commit run --all-files # run all hooks on every file
Coverage¶
Coverage is configured in .coveragerc (measuring the openspliceai package and omitting
the legacy scripts/test trees). Collect coverage while running the suite via
pytest-cov:
pytest --cov=openspliceai --cov-report=term-missing
Add --cov-report=html to generate a browsable HTML report under htmlcov/.
Continuous validation¶
There is no proprietary build system to run — validation is exactly the commands above:
pytest for behavior, ruff for static checks, and pre-commit to wire both into the
commit workflow. Because the suite is CPU-only and self-contained (all inputs are synthetic
fixtures), it can be run anywhere without GPUs or large downloads.