Skip to content

Commit 481dd76

Browse files
aylwardclaude
andauthored
ENH: HeartSimplewareTrimmedBranches + opt-in test marker overhaul (#53)
* ENH: Add HeartSimplewareTrimmedBranches as a segmentation option Default method for work involving KCL heart data * ENH: Gate slow/GPU/Simpleware tests behind --run-* flags - Add --run-slow, --run-gpu, --run-simpleware pytest flags; collection-hook auto-skips the matching markers unless the flag is passed. Mirrors the pre-existing --run-experiments / --run-tutorials pattern. - Retire the requires_data marker: 29 decorator lines removed across 17 test files. Tests that need downloadable data request the session fixtures (test_directories, download_test_data, test_images) and the data is fetched on first use. - Mark TestRegisterImagesICON, TestSegmentHeartSimpleware, and TestSegmentChestTotalSegmentator with requires_gpu so they fall into the new --run-gpu bucket. - Update self-hosted GPU workflows (ci.yml gpu-tests, test-slow.yml, nightly-health.yml) to pass every opt-in flag (--run-gpu --run-slow --run-simpleware --run-experiments --run-tutorials). Tests whose host requirements aren't met (e.g. a licensed Simpleware install) runtime-skip cleanly. - Add three unit tests to test_workflow_fit_statistical_model_to_patient covering the new HeartSimplewareTrimmedBranches default and the WorkflowConvertImageToVTK dispatch path. - Update documentation throughout (CLAUDE.md, AGENTS.md, README.md, tests/README.md, docs/testing.rst, docs/contributing.rst, docs/developer/{core,extending,segmentation}.rst, docs/api/segmentation/base.rst, .agents/agents/testing.md, .agents/skills/test-feature/SKILL.md). The test-feature skill and AGENTS.md testing role now strongly prefer real (downloaded) test data with baseline comparison over synthetic data. * ENH: Document HeartSimpleware behavior change; harden USD dispatch Address PR #53 review feedback: - Add a "Behavior change" note to the WorkflowConvertImageToVTK and WorkflowConvertImageToUSD class docstrings warning that the 'HeartSimpleware' option no longer implicitly trims branches; callers that want trimming should now select 'HeartSimplewareTrimmedBranches'. - Replace the silent else: branch in WorkflowConvertImageToUSD.__init__ with an explicit elif self.segmentation_method in (...) plus else: raise ValueError(...), matching the dispatch shape in WorkflowConvertImageToVTK._create_segmenter so a future fourth option cannot silently behave like HeartSimpleware. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent db1c416 commit 481dd76

49 files changed

Lines changed: 694 additions & 2476 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.agents/agents/testing.md

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,18 @@ pytest tests that exercise the library's scientific pipelines.
1212
- `tests/conftest.py` — session-scoped fixtures chaining: download → convert → segment → register
1313
- `tests/baselines/` — stored via Git LFS; fetch with `git lfs pull`
1414
- `src/physiomotion4d/test_tools.py` — baseline comparison utilities
15-
- Markers: `slow`, `requires_gpu`, `requires_data`, `experiment`
15+
- Markers (all opt-in via `--run-<bucket>`): `slow`, `requires_gpu`,
16+
`requires_simpleware`, `experiment`, `tutorial`. Tests that need
17+
downloadable data fetch it through the session fixtures and run by default.
1618

1719
## Run commands (use `py`, not `python`)
1820

1921
```bash
20-
py -m pytest tests/ -m "not slow and not requires_data" -v # fast, recommended
22+
py -m pytest tests/ -v # fast, recommended (slow/GPU/etc auto-skipped)
2123
py -m pytest tests/test_contour_tools.py -v # single file
22-
py -m pytest tests/test_contour_tools.py::TestContourTools -v # single class
24+
py -m pytest tests/test_contour_tools.py::TestContourTools -v # single class
25+
py -m pytest tests/ -v --run-slow # opt into slow tests
26+
py -m pytest tests/ -v --run-gpu --run-slow # typical local GPU profile (CI runner adds --run-simpleware --run-experiments --run-tutorials)
2327
py -m pytest tests/ --create-baselines # create missing baselines
2428
```
2529

@@ -28,7 +32,9 @@ py -m pytest tests/ --create-baselines # create missing b
2832
1. Read the implementation file first; understand the public interface.
2933
2. Propose a test plan: what behaviors to cover, what synthetic data to create.
3034
3. Build synthetic `itk.Image` objects or small `pv.PolyData` surfaces — 32–64 voxels/side.
31-
Never depend on real data unless unavoidable; mark those `@pytest.mark.requires_data`.
35+
When real data is unavoidable, request the standard fixtures
36+
(`test_directories`, `download_test_data`, `test_images`) — the data is
37+
downloaded automatically on first use.
3238
4. State image shape and axis order in the test docstring:
3339
e.g. `"""...image shape: (64, 64, 32), axes: X, Y, Z."""`
3440
5. Use `test_tools.py` baseline utilities for surface and image regression checks.
Lines changed: 36 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
description: Inspect a PhysioMotion4D implementation and its existing tests, propose a synthetic-data test plan, then create or update pytest tests. Explains how to run them.
2+
description: Inspect a PhysioMotion4D implementation and its existing tests, propose a real-data-driven test plan with baseline comparisons, then create or update pytest tests. Explains how to run them.
33
---
44

55
Write or update tests for the following in PhysioMotion4D:
@@ -9,10 +9,38 @@ $ARGUMENTS
99
Instructions:
1010
1. Read the implementation file(s) to understand the public interface.
1111
2. Read the existing test file for this module if one exists (e.g. `tests/test_<module>.py`).
12-
3. Propose a test plan: list the behaviors to cover and the synthetic data to create.
13-
4. Implement tests using synthetic `itk.Image` objects (32–64 voxels/side) or small
14-
`pv.PolyData` surfaces — not real patient data.
15-
5. State image shape and axis order in every test docstring.
16-
6. Mark any test that genuinely requires real data with `@pytest.mark.requires_data`.
17-
7. Show the exact command to run the new tests:
18-
`py -m pytest tests/test_<module>.py -v`
12+
3. Propose a test plan: list the behaviors to cover and the inputs each behavior
13+
needs.
14+
4. **Strongly prefer real (downloaded) test data over synthetic data.** Request
15+
the session fixtures (`test_directories`, `download_test_data`,
16+
`test_images`) so the standard test datasets are pulled automatically on
17+
first use. Real data exercises the production code paths — preprocessing,
18+
resampling, dtype handling, world-frame metadata — that synthetic toy
19+
volumes silently bypass. Only fall back to synthetic `itk.Image` or
20+
`pv.PolyData` inputs when:
21+
- the behavior under test is a pure unit (e.g. axis arithmetic, dict
22+
routing) where real data adds no signal, or
23+
- real data would push the test into a slow / GPU / Simpleware bucket
24+
that doesn't fit the test's purpose.
25+
When using synthetic inputs anyway, keep volumes ≤64 voxels per side and
26+
say so in the docstring.
27+
5. **When a test produces an image or surface as output, compare against a
28+
baseline** using the `test_tools.py` utilities (e.g. `TestTools`) rather
29+
than ad-hoc value assertions. Store baselines under `tests/baselines/`
30+
(Git LFS-tracked). Run with `--create-baselines` to materialize missing
31+
baselines on first use; afterward, regression compares to the stored
32+
baseline. This catches drift that hand-written numeric thresholds miss.
33+
6. State image shape and axis order in every test docstring (e.g.
34+
`"""...image shape: (X, Y, Z, T) = (64, 64, 32, 1), LPS world frame."""`).
35+
7. Mark tests that need a GPU, a slow runtime, or a licensed Simpleware
36+
install with `@pytest.mark.requires_gpu`, `@pytest.mark.slow`, or
37+
`@pytest.mark.requires_simpleware` so they fall into the right opt-in
38+
bucket (`--run-gpu`, `--run-slow`, `--run-simpleware`). Tests that just
39+
need downloadable data need **no** marker — the fixture chain handles it.
40+
8. Show the exact command to run the new tests, including any opt-in flags
41+
the markers require. Examples:
42+
- `py -m pytest tests/test_<module>.py -v`
43+
- `py -m pytest tests/test_<module>.py -v --run-slow`
44+
- `py -m pytest tests/test_<module>.py -v --run-gpu --run-slow`
45+
- `py -m pytest tests/test_<module>.py --create-baselines` (first run, to
46+
materialize new baselines)

.github/workflows/ci.yml

Lines changed: 28 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,13 @@ name: CI
88
# - GPU tests: Self-hosted runners with CUDA support
99
# - Code quality: Linting and formatting checks
1010
#
11-
# Test markers:
12-
# - requires_data: Tests that need external data downloads
13-
# - slow: Tests that are computationally intensive or require GPU
11+
# Test markers (gated by opt-in pytest flags; default = skip):
12+
# - slow -> --run-slow
13+
# - requires_gpu -> --run-gpu
14+
# - requires_simpleware -> --run-simpleware (also implies GPU)
15+
# - experiment -> --run-experiments
16+
# - tutorial -> --run-tutorials
17+
# Tests that need external data download it automatically via fixtures.
1418

1519
on:
1620
push:
@@ -101,16 +105,16 @@ jobs:
101105
run: |
102106
pip list
103107
104-
- name: Run unit tests (fast, no external data) - Ubuntu
108+
- name: Run unit tests (fast, no GPU/slow/experiment) - Ubuntu
105109
if: matrix.os == 'ubuntu-latest'
106110
run: |
107111
xvfb-run -a --server-args="-screen 0 1024x768x24" \
108-
pytest tests/ -v -m "not slow and not requires_data and not experiment" --cov=physiomotion4d --cov-report=xml --cov-report=term --cov-report=html
112+
pytest tests/ -v --cov=physiomotion4d --cov-report=xml --cov-report=term --cov-report=html
109113
110-
- name: Run unit tests (fast, no external data) - Windows
114+
- name: Run unit tests (fast, no GPU/slow/experiment) - Windows
111115
if: matrix.os == 'windows-latest'
112116
run: |
113-
pytest tests/ -v -m "not slow and not requires_data and not experiment" --cov=physiomotion4d --cov-report=xml --cov-report=term --cov-report=html
117+
pytest tests/ -v --cov=physiomotion4d --cov-report=xml --cov-report=term --cov-report=html
114118
115119
- name: Upload coverage to Codecov
116120
uses: codecov/codecov-action@v4
@@ -224,13 +228,13 @@ jobs:
224228

225229
- name: Run contour tools tests
226230
run: |
227-
pytest tests/test_contour_tools.py -v -m "not slow" --cov=physiomotion4d --cov-append --cov-report=xml
231+
pytest tests/test_contour_tools.py -v --cov=physiomotion4d --cov-append --cov-report=xml
228232
continue-on-error: true
229233

230234
- name: Run USD conversion tests
231235
run: |
232236
xvfb-run -a --server-args="-screen 0 1024x768x24" \
233-
pytest tests/test_convert_vtk_to_usd_polymesh.py -v -m "not slow" --cov=physiomotion4d --cov-append --cov-report=xml
237+
pytest tests/test_convert_vtk_to_usd_polymesh.py -v --cov=physiomotion4d --cov-append --cov-report=xml
234238
continue-on-error: true
235239

236240
- name: Run USD utility tests
@@ -242,7 +246,7 @@ jobs:
242246
- name: Run all integration tests
243247
run: |
244248
xvfb-run -a --server-args="-screen 0 1024x768x24" \
245-
pytest tests/ -v -m "not slow and not experiment and not requires_gpu"
249+
pytest tests/ -v
246250
continue-on-error: true
247251

248252
- name: Upload coverage to Codecov
@@ -325,8 +329,12 @@ jobs:
325329
pip list
326330
327331
- name: Run GPU tests
332+
# External self-hosted GPU runner: enable every opt-in bucket.
333+
# Tests whose host requirements (e.g. a licensed Simpleware install)
334+
# aren't met on the runner will runtime-skip cleanly via their
335+
# internal availability guards.
328336
run: |
329-
pytest tests/ -v -m "not slow and not experiment" --cov=physiomotion4d --cov-report=xml --cov-report=term --cov-report=html
337+
pytest tests/ -v --run-gpu --run-slow --run-simpleware --run-experiments --run-tutorials --cov=physiomotion4d --cov-report=xml --cov-report=term --cov-report=html
330338
env:
331339
CUDA_VISIBLE_DEVICES: 0
332340

@@ -404,11 +412,14 @@ jobs:
404412
# They execute end-to-end workflows that may take multiple hours
405413
#
406414
# To run locally:
407-
# pytest tests/ -v -m "slow" # Run all slow tests
408-
# pytest tests/test_register_images_ants.py -v
409-
# pytest tests/test_register_images_icon.py -v
410-
# pytest tests/test_segment_chest_total_segmentator.py -v
415+
# pytest tests/ -v --run-slow # Run all slow tests
416+
# pytest tests/ -v --run-gpu --run-slow # GPU + slow (typical local dev profile)
417+
# pytest tests/ -v --run-simpleware --run-gpu --run-slow # Full Simpleware coverage
418+
# pytest tests/test_register_images_ants.py -v --run-slow
419+
#
420+
# Self-hosted GPU runner enables ALL buckets:
421+
# --run-gpu --run-slow --run-simpleware --run-experiments --run-tutorials
411422
#
412423
# To run experiment tests (manual only, extremely slow):
413-
# pytest tests/test_experiments.py -v -m experiment
414-
# pytest tests/test_experiments.py::test_experiment_heart_gated_ct_to_usd -v
424+
# pytest tests/test_experiments.py -v --run-experiments
425+
# pytest tests/test_experiments.py::test_experiment_heart_gated_ct_to_usd -v --run-experiments

.github/workflows/nightly-health.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ jobs:
108108
# The step outcome (success/failure) is still captured and passed downstream.
109109
continue-on-error: true
110110
run: |
111-
pytest tests/ -v --run-experiments `
111+
pytest tests/ -v --run-experiments --run-tutorials --run-slow --run-gpu --run-simpleware `
112112
--cov=physiomotion4d `
113113
--cov-report=xml `
114114
--cov-report=json `

.github/workflows/test-slow.yml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,12 @@ jobs:
7272
"
7373
7474
- name: Run slow tests
75+
# Self-hosted GPU runner: enable every opt-in bucket.
76+
# Tests whose host requirements (e.g. a licensed Simpleware install)
77+
# aren't met on the runner will runtime-skip cleanly via their
78+
# internal availability guards.
7579
run: |
76-
pytest tests/ -v -m "slow and not experiment" --cov=physiomotion4d --cov-report=xml --cov-report=term
80+
pytest tests/ -v --run-slow --run-gpu --run-simpleware --run-experiments --run-tutorials --cov=physiomotion4d --cov-report=xml --cov-report=term
7781
env:
7882
CUDA_VISIBLE_DEVICES: 0
7983

AGENTS.md

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,11 @@ Non-Python tools used by contributor workflows:
2929
`self.log_debug()` — never `print()`. Standalone scripts may use `print()`.
3030
- Single quotes for strings; double quotes for docstrings. 88-char line limit.
3131
- Full type hints (`mypy` strict). Use `Optional[X]` not `X | None`.
32-
- Run `py -m pytest tests/ -m "not slow and not requires_data" -v` to verify changes.
32+
- Run `py -m pytest tests/ -v` to verify changes. Slow / GPU / Simpleware /
33+
experiment / tutorial tests are auto-skipped; opt in per bucket with
34+
`--run-slow`, `--run-gpu`, `--run-simpleware`, `--run-experiments`,
35+
`--run-tutorials`. The `requires_data` marker no longer exists — tests that
36+
need external data download it automatically via the session fixtures.
3337
- Consult `docs/API_MAP.md` to locate classes and methods before searching manually.
3438

3539
## Implementation role
@@ -41,11 +45,27 @@ Non-Python tools used by contributor workflows:
4145

4246
## Testing role
4347

44-
- Prefer synthetic `itk.Image` and small `pv.PolyData` surfaces — not real patient data.
45-
- State image shape and axis order in every test docstring: e.g. `shape (X, Y, Z, T)`.
46-
- Keep synthetic volumes ≤64 voxels per side for speed.
47-
- Mark tests that genuinely need real data with `@pytest.mark.requires_data`.
48-
- Use `test_tools.py` baseline utilities for surface and image regression checks.
48+
- **Strongly prefer real (downloaded) test data over synthetic data.** Request
49+
the session fixtures (`test_directories`, `download_test_data`,
50+
`test_images`) so the standard datasets are fetched automatically on first
51+
use. Real data exercises preprocessing, resampling, dtype handling, and
52+
world-frame metadata paths that synthetic toy volumes silently bypass.
53+
- Only fall back to synthetic `itk.Image` or `pv.PolyData` inputs when the
54+
behavior under test is a pure unit (axis arithmetic, dict routing, etc.)
55+
where real data adds no signal, or when real data would push the test into
56+
a slow/GPU/Simpleware bucket that doesn't fit the test's purpose. Keep
57+
synthetic volumes ≤64 voxels per side and say so in the docstring.
58+
- State image shape and axis order in every test docstring: e.g.
59+
`shape (X, Y, Z, T) = (64, 64, 32, 1), LPS world frame`.
60+
- **When a test produces an image or surface, compare against a baseline**
61+
using `test_tools.py` utilities (e.g. `TestTools`) and store baselines under
62+
`tests/baselines/` (Git LFS-tracked). Run with `--create-baselines` to
63+
materialize missing baselines on first use.
64+
- Mark tests that need a GPU, a slow runtime, or a licensed Simpleware
65+
install with `@pytest.mark.requires_gpu`, `@pytest.mark.slow`, or
66+
`@pytest.mark.requires_simpleware` so they fall into the right opt-in
67+
bucket. Tests that just need downloadable data need no marker — the
68+
fixture chain handles it.
4969

5070
## Documentation role
5171

CLAUDE.md

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -38,23 +38,28 @@ mypy src/ tests/
3838
# All pre-commit hooks
3939
pre-commit run --all-files
4040

41-
# Fast tests (recommended for development)
42-
py -m pytest tests/ -m "not slow and not requires_data" -v
41+
# Fast tests (recommended for development — slow/GPU/Simpleware/experiment
42+
# /tutorial tests are auto-skipped unless their opt-in flag is passed)
43+
py -m pytest tests/ -v
4344

4445
# Single test file or test by name
4546
py -m pytest tests/test_contour_tools.py -v
4647
py -m pytest tests/test_contour_tools.py::test_extract_surface -v
4748

48-
# Skip GPU-dependent tests
49-
py -m pytest tests/ --ignore=tests/test_segment_chest_total_segmentator.py \
50-
--ignore=tests/test_register_images_icon.py
49+
# Opt-in buckets (each flag enables one marker family)
50+
py -m pytest tests/ -v --run-slow # tests marked 'slow'
51+
py -m pytest tests/ -v --run-gpu # tests marked 'requires_gpu'
52+
py -m pytest tests/ -v --run-simpleware # tests marked 'requires_simpleware'
53+
py -m pytest tests/ -v --run-experiments # tests marked 'experiment'
54+
py -m pytest tests/ -v --run-tutorials # tests marked 'tutorial'
55+
56+
# Typical local GPU profile. The self-hosted CI GPU runner enables every
57+
# bucket: --run-gpu --run-slow --run-simpleware --run-experiments --run-tutorials
58+
py -m pytest tests/ -v --run-gpu --run-slow
5159

5260
# With coverage
5361
py -m pytest tests/ --cov=src/physiomotion4d --cov-report=html
5462

55-
# Experiment script tests (very slow, opt-in)
56-
py -m pytest tests/ --run-experiments
57-
5863
# Create missing baselines
5964
py -m pytest tests/ --create-baselines
6065
```
@@ -86,7 +91,9 @@ Regenerate it after any public API change: `py utils/generate_api_map.py`
8691
- Baselines in `tests/baselines/` via Git LFS — run `git lfs pull` after cloning
8792
- `tests/conftest.py`: session-scoped fixtures chaining download → convert → segment → register
8893
- `src/physiomotion4d/test_tools.py`: baseline comparison utilities (`TestTools`, etc.)
89-
- Markers: `slow`, `requires_gpu`, `requires_data`, `experiment`, `tutorial`
94+
- Markers (all opt-in via `--run-<bucket>`): `slow`, `requires_gpu`,
95+
`requires_simpleware`, `experiment`, `tutorial`. Data-dependent tests no
96+
longer use a marker — they pull data through fixtures and run by default.
9097
- Prefer images from `ROOT/data/test/slicer_heart_small` for tests
9198
- Prefer storing results in subdirs `./results/<test_name>`
9299

README.md

Lines changed: 25 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -632,27 +632,34 @@ See `docs/contributing.rst` for complete IDE setup instructions.
632632
PhysioMotion4D includes comprehensive tests covering the complete pipeline from data download to USD generation.
633633

634634
```bash
635-
# Run all tests
636-
pytest tests/
637-
638-
# Run fast tests only (recommended for development)
639-
pytest tests/ -m "not slow and not requires_data" -v
635+
# Fast tests (recommended for development).
636+
# slow / GPU / Simpleware / experiment / tutorial tests are auto-skipped
637+
# unless their opt-in flag is passed (see below). Tests that need
638+
# downloadable data fetch it automatically via the session fixtures.
639+
pytest tests/ -v
640+
641+
# Opt-in buckets (each flag enables one marker family)
642+
pytest tests/ -v --run-slow # tests marked 'slow'
643+
pytest tests/ -v --run-gpu # tests marked 'requires_gpu'
644+
pytest tests/ -v --run-simpleware # tests marked 'requires_simpleware'
645+
pytest tests/ -v --run-experiments # tests marked 'experiment'
646+
pytest tests/ -v --run-tutorials # tests marked 'tutorial'
647+
648+
# Typical local GPU profile. The self-hosted CI GPU runner enables every
649+
# bucket: --run-gpu --run-slow --run-simpleware --run-experiments --run-tutorials
650+
pytest tests/ -v --run-gpu --run-slow
640651

641652
# Run specific test categories
642653
pytest tests/test_usd_merge.py -v # USD merge functionality
643654
pytest tests/test_usd_time_preservation.py -v # Time-varying data preservation
644-
pytest tests/test_register_images_ants.py -v # ANTs registration
645-
pytest tests/test_register_images_greedy.py -v # Greedy registration
646-
pytest tests/test_register_images_icon.py -v # Icon registration
647-
pytest tests/test_register_time_series_images.py -v # Time series registration
648-
pytest tests/test_segment_chest_total_segmentator.py -v # TotalSegmentator
655+
pytest tests/test_register_images_ants.py -v --run-slow # ANTs registration
656+
pytest tests/test_register_images_greedy.py -v # Greedy registration
657+
pytest tests/test_register_images_icon.py -v --run-gpu --run-slow # Icon registration (GPU)
658+
pytest tests/test_register_time_series_images.py -v --run-slow # Time series registration
659+
pytest tests/test_segment_chest_total_segmentator.py -v --run-slow # TotalSegmentator
649660
pytest tests/test_contour_tools.py -v # Mesh and contour tools
650661
pytest tests/test_image_tools.py -v # Image processing utilities
651-
pytest tests/test_transform_tools.py -v # Transform operations
652-
653-
# Skip GPU-dependent tests (segmentation and registration)
654-
pytest tests/ --ignore=tests/test_segment_chest_total_segmentator.py \
655-
--ignore=tests/test_register_images_icon.py
662+
pytest tests/test_transform_tools.py -v --run-slow # Transform operations
656663

657664
# Run with coverage report
658665
pytest tests/ --cov=src/physiomotion4d --cov-report=html
@@ -742,9 +749,9 @@ Use `/test-feature` to get a test plan and a complete pytest file using syntheti
742749
/test-feature RegisterImagesANTs with a pair of small synthetic ITK images
743750
```
744751

745-
The agent will state image shapes and axis orders in every test docstring, mark
746-
any real-data dependency with `@pytest.mark.requires_data`, and show the exact
747-
run command.
752+
The agent will state image shapes and axis orders in every test docstring, wire
753+
real-data dependencies through the session fixtures (so the data is downloaded
754+
on first use), and show the exact run command.
748755

749756
---
750757

0 commit comments

Comments
 (0)