Contributing and testing¶
Development setup¶
The source repository is private (maintainers only); the public repository
humansys-lab/ecg-records holds the documentation, schemas and examples.
git clone git@github.com:humansys-lab/ECG-feature-extraction-.git # private
cd ECG-feature-extraction-
python -m venv .venv && source .venv/bin/activate
python -m pip install -r requirements-ci.txt
python -m pip install -e "./feature_extraction[dev]"
python -m pip install "mkdocs>=1.6,<2"
requirements-ci.txt lists the test dependencies (pytest, Hypothesis,
jsonschema, Matplotlib, wfdb). The dev extra adds build, twine and
import-linter. The package itself only needs NumPy and SciPy.
Running the checks¶
| Check | Command |
|---|---|
| test suite | python -m pytest -q tests |
| import-layer contracts | lint-imports --config feature_extraction/.importlinter |
| validation registry | python tools/check_validation_registry.py |
| changelog has the current version | python tools/check_changelog.py |
| performance budget | python tools/check_performance.py reference --repeats 5 |
| generated reference pages are current | python tools/build_docs.py --check |
| documentation examples run | python tools/check_doc_examples.py |
| documentation site builds | mkdocs build --strict |
CI (.github/workflows/test.yml) runs all of them on every pull request.
Optional dependencies in tests¶
- Tests that need Matplotlib (
tests/viz/) are skipped when it is not installed; the import-isolation tests always run. - The legacy
ECGFeatureExtractor.extract()path and the legacy JSON export include the interpretation, which lives in the separateecginterpretdistribution. Their tests are marked@needs_interpretation(tests/optional.py) and skip unlessecginterpretis installed. The record API is tested unconditionally. - Tests that read public datasets skip unless the data is present (for example
LUDB under
data/).
Test layout¶
| Kind | Examples |
|---|---|
| record contract and schema | test_ecg_record_contract.py, test_library_design_review.py, test_record_sidecar.py |
| property tests (Hypothesis) | test_record_properties.py |
| pinned reference record | test_golden_reference.py, fixture tests/fixtures/golden/reference_10s_12lead/ |
| pipeline, stages, policies | test_pipeline_decomposition.py, test_pacing_policy.py, test_limited_leads.py |
| engine behaviour | test_atrial_events.py, test_af_afl_features.py, test_quality_contract.py, … |
| public facade and deprecations | test_public_facade.py, test_engine_relocation.py |
| plotting | tests/viz/ |
| tools | test_performance_budget.py, test_validation_registry.py |
The reference fixture¶
tests/fixtures/golden/reference_10s_12lead/ holds a synthetic 10 s, 12-lead,
500 Hz signal (signal.npz, generated by make_signal.py) and its expected
records in all three profiles. test_golden_reference.py requires the current
code to reproduce them exactly. When a reviewed change alters the records,
regenerate them with python tests/fixtures/golden/update_fixture.py and
explain the difference in the pull request.
Documentation¶
The site lives in docs/site/ and is built with MkDocs (mkdocs.yml).
docs/site/reference/is generated from the installed package and the shipped schema files bypython tools/build_docs.py. Do not edit it by hand; CI fails when it is stale.- Every
```pythonblock in the guide is executed bytools/check_doc_examples.py, in a scratch directory that containsecg.npyandecg.npz(the reference signal) andecg.record.json(its record). Blocks on one page share a namespace, in order. A block that needs files the checker cannot provide is preceded by<!-- doc-check: skip (...) -->. - The full example record in
guide/record-format.mdis validated against the JSON Schema and the strict reader bytest_library_design_review.py. - Preview locally with
mkdocs serve. Every push tomainthat touches the docs, the package or the schemas rebuilds the site with the same checks and deploys it to GitHub Pages (.github/workflows/docs.yml), at https://humansys-lab.github.io/ECG-feature-extraction-/.
Style¶
- Public functions take keyword-only options and validate their inputs.
- Errors are
ECGInputErrorsubclasses with a stablecode. - Records must stay deterministic: no randomness, no timestamps, sorted keys.
- Keep the layer rules;
lint-importsenforces them.