Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
5084800
Add test-suite-and-validation ADR suggestion
AndrewSazonov Jun 5, 2026
472a0dd
Update test-suite-and-validation ADR and index from review
AndrewSazonov Jun 5, 2026
c4d0532
Add test-suite-and-validation implementation plan
AndrewSazonov Jun 5, 2026
36609da
Make codecov patch informational and gate project at 80%
AndrewSazonov Jun 5, 2026
4db5ee9
Replace fast marker with pr and nightly test tiers
AndrewSazonov Jun 5, 2026
f1710a7
Select test tiers per trigger across all test layers
AndrewSazonov Jun 5, 2026
29701b7
Gate unit-test structure check on shared src tree walk
AndrewSazonov Jun 5, 2026
8f68124
Document strict test layer placement criteria
AndrewSazonov Jun 5, 2026
906f20d
Relocate network and engine tests to correct layers
AndrewSazonov Jun 5, 2026
6bfc73d
Document integration layer defaults to pr tier
AndrewSazonov Jun 5, 2026
31f8882
Add hypothesis deterministic profile and shared test fixtures
AndrewSazonov Jun 5, 2026
146ad57
Add property-based input-domain tests for validators
AndrewSazonov Jun 6, 2026
dc90a36
Raise coverage fail_under to 80 percent
AndrewSazonov Jun 6, 2026
aacc3e6
Add strict docs build and spell check on every push
AndrewSazonov Jun 6, 2026
60b7d8a
Add calculator support matrix query for verification
AndrewSazonov Jun 6, 2026
8cc7e2a
Add cross-engine verification comparison pages and script wiring
AndrewSazonov Jun 6, 2026
0c9ffb7
Add per-experiment performance benchmarks (nightly)
AndrewSazonov Jun 6, 2026
2dcb98d
Record cross-repo nightly harness and benchmarks as future work
AndrewSazonov Jun 6, 2026
d025df7
Promote test-suite-and-validation ADR to accepted
AndrewSazonov Jun 6, 2026
78450c4
Reach Phase 1 review gate
AndrewSazonov Jun 6, 2026
a2a23a3
Run pr tier on pull_request events, not only main branches
AndrewSazonov Jun 6, 2026
7ccd28f
Share excluded-dirs set between structure check and docs
AndrewSazonov Jun 6, 2026
5edcc7b
Add lychee link check to the docs gate
AndrewSazonov Jun 6, 2026
f9a1730
Run verification notebooks in notebook test and exec tasks
AndrewSazonov Jun 6, 2026
0262ed3
Assert explicit tolerances for all verification metrics
AndrewSazonov Jun 6, 2026
eb3aee0
Run full suite across all tiers in the nightly workflow
AndrewSazonov Jun 6, 2026
7d02a24
Scope verification to CWL powder now, defer rest to issue 115
AndrewSazonov Jun 6, 2026
64168ae
Lint and format verification pages like tutorials
AndrewSazonov Jun 6, 2026
81e521d
Apply pixi run fix auto-fixes and resolve lint findings
AndrewSazonov Jun 6, 2026
7ce29db
Tighten cross-engine verification tolerances from measurement
AndrewSazonov Jun 6, 2026
4f4de17
Render small canvas in raster tests to speed them up
AndrewSazonov Jun 6, 2026
83bd6a5
Add icon to the Verification docs section
AndrewSazonov Jun 6, 2026
ede35b7
Fix tabel typo in docs CSS comments
AndrewSazonov Jun 6, 2026
9bc03a2
Fix promoted ADR links to documentation-ci-build
AndrewSazonov Jun 6, 2026
54b6d48
Scope codespell and lychee to pass on real sources
AndrewSazonov Jun 6, 2026
bb2c967
Run docs checks (spell, link, strict build) with the checks
AndrewSazonov Jun 6, 2026
2dbb6f0
Reflow ADR prose after link fix
AndrewSazonov Jun 6, 2026
2f2a40d
Make check static-only and add full pre-PR all task
AndrewSazonov Jun 6, 2026
c1afbd2
Always build docs strictly; drop docs-build-strict
AndrewSazonov Jun 6, 2026
aee2a76
Gate docstring coverage as a check, not in coverage.yml
AndrewSazonov Jun 6, 2026
5046b05
Restore logger reaction mode in validation-properties test
AndrewSazonov Jun 6, 2026
6950251
Expand unit-test coverage across analysis, display, report
AndrewSazonov Jun 6, 2026
c292d89
Add coverage tests for tex_renderer, iucr_writer, serialize, tracking
AndrewSazonov Jun 6, 2026
a1c244f
Add coverage tests for project display, logging, utils, experiment item
AndrewSazonov Jun 6, 2026
173ce6f
Add coverage tests for plotting, analysis, plotly, project
AndrewSazonov Jun 6, 2026
ef8b055
Add coverage tests for sequential, environment, sidecar, collection
AndrewSazonov Jun 6, 2026
e79388d
Add docstrings across analysis, datablocks, display modules
AndrewSazonov Jun 6, 2026
71b2351
Fix diagonal-shape call in single-crystal predictive plot
AndrewSazonov Jun 6, 2026
a69f246
Make relative-destination zip test hermetic
AndrewSazonov Jun 6, 2026
71bc681
Harden unit-test gate: random order, state reset, 88% floor
AndrewSazonov Jun 6, 2026
2f1876e
Fix two unit tests that relied on leaked WARN logger mode
AndrewSazonov Jun 6, 2026
be9fd20
Add open issue: static type checker in the quality gate
AndrewSazonov Jun 6, 2026
4304821
Record pytest-randomly dependency approval in the plan
AndrewSazonov Jun 6, 2026
218742b
Skip integration tests on the fast tier instead of failing
AndrewSazonov Jun 6, 2026
990e681
Fix two Windows-only failures in coverage tests
AndrewSazonov Jun 6, 2026
0754105
Use in-memory HDF5 for low-level sidecar unit tests
AndrewSazonov Jun 6, 2026
d0f8f99
Scope display_path relative_to patch to the target only
AndrewSazonov Jun 6, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions .codecov.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,16 @@ coverage:
status:
project:
default:
target: auto
target: 80%
threshold: 1%
# Make project coverage informational (won't block PR)
informational: true
# Project coverage is the real gate (see ADR
# test-suite-and-validation).
informational: false
patch:
default:
target: auto
# Require patch coverage but with threshold
threshold: 1%
# Non-blocking: patch grades diff lines against unit-only
# coverage, so engine/integration-tested code would otherwise
# always fail. See ADR test-suite-and-validation.
informational: true
19 changes: 3 additions & 16 deletions .github/workflows/coverage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,21 +26,8 @@ env:
CI_BRANCH: ${{ github.head_ref || github.ref_name }}

jobs:
# Job 1: Run docstring coverage
docstring-coverage:
runs-on: ubuntu-latest

steps:
- name: Check-out repository
uses: actions/checkout@v6

- name: Set up pixi
uses: ./.github/actions/setup-pixi

- name: Run docstring coverage
run: pixi run docstring-coverage

# Job 2: Run unit tests with coverage and upload to Codecov
# Job 1: Run unit tests with coverage and upload to Codecov.
# Docstring coverage is gated as a static check in lint-format.yml.
unit-tests-coverage:
runs-on: ubuntu-latest

Expand All @@ -65,6 +52,6 @@ jobs:

# Job 4: Build and publish dashboard (reusable workflow)
run-reusable-workflows:
needs: [docstring-coverage, unit-tests-coverage] # depend on the previous jobs
needs: [unit-tests-coverage] # depend on the previous job
uses: ./.github/workflows/dashboard.yml
secrets: inherit
40 changes: 40 additions & 0 deletions .github/workflows/lint-format.yml
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,12 @@ jobs:
shell: bash
run: pixi run docstring-lint-check

- name: Check docstring coverage (interrogate)
id: docstring_coverage
continue-on-error: true
shell: bash
run: pixi run docstring-coverage

- name: Check formatting of non-Python files (md, toml, etc.)
id: nonpy_format
continue-on-error: true
Expand All @@ -91,6 +97,30 @@ jobs:
shell: bash
run: pixi run notebook-lint-check

- name: Check unit-test directory mirrors src/ structure
id: test_structure
continue-on-error: true
shell: bash
run: pixi run test-structure-check

- name: Check spelling (codespell)
id: spell
continue-on-error: true
shell: bash
run: pixi run spell-check

- name: Check documentation links (lychee)
id: link
continue-on-error: true
shell: bash
run: pixi run link-check

- name: Build documentation strictly (no tutorial execution)
id: docs_build
continue-on-error: true
shell: bash
run: pixi run docs-build

# Add summary
- name: Add quality checks summary
if: always()
Expand All @@ -106,8 +136,13 @@ jobs:
echo "| py lint | ${{ steps.py_lint.outcome == 'success' && '✅' || '❌' }} |"
echo "| py format | ${{ steps.py_format.outcome == 'success' && '✅' || '❌' }} |"
echo "| docstring lint | ${{ steps.docstring_lint.outcome == 'success' && '✅' || '❌' }} |"
echo "| docstring cover | ${{ steps.docstring_coverage.outcome == 'success' && '✅' || '❌' }} |"
echo "| nonpy format | ${{ steps.nonpy_format.outcome == 'success' && '✅' || '❌' }} |"
echo "| notebooks lint | ${{ steps.notebook_lint.outcome == 'success' && '✅' || '❌' }} |"
echo "| test structure | ${{ steps.test_structure.outcome == 'success' && '✅' || '❌' }} |"
echo "| spelling | ${{ steps.spell.outcome == 'success' && '✅' || '❌' }} |"
echo "| doc links | ${{ steps.link.outcome == 'success' && '✅' || '❌' }} |"
echo "| docs strict build| ${{ steps.docs_build.outcome == 'success' && '✅' || '❌' }} |"
} >> "$GITHUB_STEP_SUMMARY"

# Fail job if any check failed
Expand All @@ -118,7 +153,12 @@ jobs:
|| steps.py_lint.outcome == 'failure'
|| steps.py_format.outcome == 'failure'
|| steps.docstring_lint.outcome == 'failure'
|| steps.docstring_coverage.outcome == 'failure'
|| steps.nonpy_format.outcome == 'failure'
|| steps.notebook_lint.outcome == 'failure'
|| steps.test_structure.outcome == 'failure'
|| steps.spell.outcome == 'failure'
|| steps.link.outcome == 'failure'
|| steps.docs_build.outcome == 'failure'
shell: bash
run: exit 1
45 changes: 45 additions & 0 deletions .github/workflows/nightly.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# Nightly run of the FULL test suite across all cost tiers (default, pr,
# and nightly), plus the performance benchmarks. The per-push and per-PR
# runs in test.yml deselect the pr/nightly tiers; the nightly run does
# not. See ADR test-suite-and-validation.

name: Nightly tests

on:
# Run the nightly-tier tests on a daily schedule
schedule:
- cron: '0 3 * * *' # 03:00 UTC daily
# Allow manual runs from the Actions tab
workflow_dispatch:

permissions:
contents: read

# Allow only one concurrent nightly run per ref.
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
nightly-tests:
runs-on: ubuntu-latest

steps:
- name: Check-out repository
uses: actions/checkout@v6

- name: Set up pixi
uses: ./.github/actions/setup-pixi

- name: Run the full test suite (all tiers)
run: pixi run test-all

- name: Run performance benchmarks
run: pixi run benchmarks

- name: Upload benchmark results
if: ${{ !cancelled() }}
uses: ./.github/actions/upload-artifact
with:
name: benchmark-results
path: benchmark.json
41 changes: 30 additions & 11 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,17 +54,29 @@ jobs:

outputs:
pytest-marks: ${{ steps.set-mark.outputs.pytest_marks }}
run-pr-tier: ${{ steps.set-mark.outputs.run_pr_tier }}

steps:
# Determine if integration tests should be run fully or only the fast ones
# (to save time on branches other than master and develop)
- name: Set mark for integration tests
# Select the test cost tier by branch (see ADR test-suite-and-validation):
# the pr tier runs on develop/master and pull requests; feature-branch
# pushes run only the default (fast) tier. The nightly tier runs
# separately in nightly.yml.
- name: Set test tier marker expression
id: set-mark
run: |
if [[ "${{ env.CI_BRANCH }}" == "master" || "${{ env.CI_BRANCH }}" == "develop" ]]; then
echo "pytest_marks=" >> $GITHUB_OUTPUT
# Pull requests and develop/master pushes run the pr tier;
# feature-branch pushes run only the default (fast) tier. On a
# pull_request event CI_BRANCH is the contributor branch, so the
# event type must be checked explicitly. run_pr_tier gates the
# integration steps: the integration layer is entirely pr-marked,
# so on the fast tier its selection is empty and pytest would exit
# 5 ("no tests collected"); skip the step in that case instead.
if [[ "${{ github.event_name }}" == "pull_request" || "${{ env.CI_BRANCH }}" == "master" || "${{ env.CI_BRANCH }}" == "develop" ]]; then
echo 'pytest_marks=-m "not nightly"' >> "$GITHUB_OUTPUT"
echo 'run_pr_tier=true' >> "$GITHUB_OUTPUT"
else
echo "pytest_marks=-m fast" >> $GITHUB_OUTPUT
echo 'pytest_marks=-m "not pr and not nightly"' >> "$GITHUB_OUTPUT"
echo 'run_pr_tier=false' >> "$GITHUB_OUTPUT"
fi

# Job 2: Test code
Expand Down Expand Up @@ -99,7 +111,7 @@ jobs:
env="py-$(echo $py_ver | tr -d .)-env" # Converts 3.XX -> py-3XX-env

echo "Running tests in environment: $env"
pixi run --environment $env unit-tests
pixi run --environment $env unit-tests ${{ needs.env-prepare.outputs.pytest-marks }}
done

- name: Run functional tests
Expand All @@ -114,10 +126,14 @@ jobs:
env="py-$(echo $py_ver | tr -d .)-env" # Converts 3.XX -> py-3XX-env

echo "Running tests in environment: $env"
pixi run --environment $env functional-tests
pixi run --environment $env functional-tests ${{ needs.env-prepare.outputs.pytest-marks }}
done

# Integration tests are entirely pr-marked, so they only run in the pr
# tier (PRs + develop/master). On feature-branch pushes the selection
# would be empty; skip the step rather than fail on pytest exit code 5.
- name: Run integration tests ${{ needs.env-prepare.outputs.pytest-marks }}
if: needs.env-prepare.outputs.run-pr-tier == 'true'
shell: bash
run: |
set -euo pipefail
Expand Down Expand Up @@ -173,7 +189,8 @@ jobs:

# Job 3: Test the package
package-test:
needs: source-test # depend on previous job
# env-prepare provides the tier marker expression; source-test the wheel
needs: [env-prepare, source-test]

strategy:
fail-fast: false
Expand Down Expand Up @@ -270,7 +287,7 @@ jobs:
cd easydiffraction_py$py_ver

echo "Running tests"
pixi run python -m pytest ../tests/unit/ --color=yes -v
pixi run python -m pytest ../tests/unit/ --color=yes -v ${{ needs.env-prepare.outputs.pytest-marks }}

echo "Exiting pixi project directory"
cd ..
Expand All @@ -289,13 +306,15 @@ jobs:
cd easydiffraction_py$py_ver

echo "Running tests"
pixi run python -m pytest ../tests/functional/ --color=yes -v
pixi run python -m pytest ../tests/functional/ --color=yes -v ${{ needs.env-prepare.outputs.pytest-marks }}

echo "Exiting pixi project directory"
cd ..
done

# See the source-test job: integration tests run only in the pr tier.
- name: Run integration tests ${{ needs.env-prepare.outputs.pytest-marks }}
if: needs.env-prepare.outputs.run-pr-tier == 'true'
shell: bash
run: |
set -euo pipefail
Expand Down
19 changes: 13 additions & 6 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,13 @@ repos:
pass_filenames: false
stages: [manual]

- id: pixi-docstring-coverage
name: pixi run docstring-coverage
entry: pixi run docstring-coverage
language: system
pass_filenames: false
stages: [manual]

- id: pixi-nonpy-format-check
name: pixi run nonpy-format-check
entry: pixi run nonpy-format-check
Expand All @@ -60,16 +67,16 @@ repos:
pass_filenames: false
stages: [manual]

- id: pixi-unit-tests
name: pixi run unit-tests
entry: pixi run unit-tests
- id: pixi-spell-check
name: pixi run spell-check
entry: pixi run spell-check
language: system
pass_filenames: false
stages: [manual]

- id: pixi-functional-tests
name: pixi run functional-tests
entry: pixi run functional-tests
- id: pixi-link-check
name: pixi run link-check
entry: pixi run link-check
language: system
pass_filenames: false
stages: [manual]
9 changes: 9 additions & 0 deletions docs/dev/adrs/accepted/test-strategy.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,12 @@ aliases.
New features should add focused tests at the lowest useful layer and
broader tests when behavior crosses module boundaries. The mirrored
structure makes missing coverage easier to spot.

## Amendments

[Test Suite and Validation Strategy](test-suite-and-validation.md)
sharpens these layer definitions into strict, testable placement
criteria and adds test cost tiers, coverage policy, codecov
configuration, cross-engine verification documentation, and a nightly
validation harness. The practical placement rules live in the
[Testing Guide](../../testing-guide.md).
Loading
Loading