22import runpy
33import subprocess
44import sys
5- from pathlib import Path
65from unittest .mock import patch
76
87import matplotlib .pyplot as plt
98import pytest
109
11- DOCS = Path (__file__ ).parent .parent / "docs"
12- EXAMPLES = DOCS / "examples"
10+ # Examples per test, relative to docs/examples: either explicit files or a glob pattern.
11+ _EXAMPLES = {
12+ "test_maintenance_examples" : [
13+ "maintenance/QLIPP_simulation/2D_QLIPP_forward.py" ,
14+ "maintenance/QLIPP_simulation/2D_QLIPP_recon.py" ,
15+ "maintenance/PTI_simulation/PTI_Simulation_Forward_2D3D.py" ,
16+ "maintenance/PTI_simulation/PTI_Simulation_Recon2D.py" ,
17+ "maintenance/PTI_simulation/PTI_Simulation_Recon3D.py" ,
18+ ],
19+ "test_demo_examples" : [
20+ "demos/QPI_defocus/QPI_defocus_simulation.py" ,
21+ "demos/QLIPP/QLIPP_simulation.py" ,
22+ ],
23+ "test_api_examples" : "api/*.py" ,
24+ "test_cli_examples" : "cli/*.sh" ,
25+ }
26+
27+
28+ def pytest_generate_tests (metafunc ):
29+ """Resolve repository examples from pytest's configured project root."""
30+ entry = _EXAMPLES .get (metafunc .function .__name__ )
31+ if entry is None :
32+ return
33+
34+ examples_dir = metafunc .config .rootpath / "docs" / "examples"
35+ if isinstance (entry , str ):
36+ examples = sorted (examples_dir .glob (entry ))
37+ else :
38+ examples = [examples_dir / name for name in entry ]
39+ metafunc .parametrize ("example" , examples , ids = lambda path : path .name )
1340
1441
15- @pytest .mark .parametrize (
16- "example" ,
17- [
18- EXAMPLES / "maintenance" / "QLIPP_simulation/2D_QLIPP_forward.py" ,
19- EXAMPLES / "maintenance" / "QLIPP_simulation/2D_QLIPP_recon.py" ,
20- EXAMPLES / "maintenance" / "PTI_simulation/PTI_Simulation_Forward_2D3D.py" ,
21- EXAMPLES / "maintenance" / "PTI_simulation/PTI_Simulation_Recon2D.py" ,
22- EXAMPLES / "maintenance" / "PTI_simulation/PTI_Simulation_Recon3D.py" ,
23- ],
24- ids = lambda p : p .name ,
25- )
2642def test_maintenance_examples (example ):
2743 """Test maintenance examples (QLIPP, PTI) with mocked plotting"""
2844 with (
@@ -39,14 +55,6 @@ def test_maintenance_examples(example):
3955 plt .close ("all" )
4056
4157
42- @pytest .mark .parametrize (
43- "example" ,
44- [
45- EXAMPLES / "demos/QPI_defocus/QPI_defocus_simulation.py" ,
46- EXAMPLES / "demos/QLIPP/QLIPP_simulation.py" ,
47- ],
48- ids = lambda p : p .name ,
49- )
5058def test_demo_examples (example ):
5159 """Run Colab demo scripts so renamed APIs in waveorder are caught early.
5260
@@ -80,9 +88,9 @@ def test_demo_examples(example):
8088 "inplane_oriented_thick_pol3d.py" ,
8189 ],
8290)
83- def test_phase_examples (script ):
91+ def test_phase_examples (script , pytestconfig ):
8492 """Test phase model examples"""
85- path = EXAMPLES / "models" / script
93+ path = pytestconfig . rootpath / "docs" / "examples" / "models" / script
8694 # examples needs two <enters>s so send input="e\ne"
8795 completed_process = subprocess .run (
8896 [sys .executable , str (path )],
@@ -93,21 +101,11 @@ def test_phase_examples(script):
93101 assert completed_process .returncode == 0
94102
95103
96- @pytest .mark .parametrize (
97- "example" ,
98- sorted ((EXAMPLES / "api" ).glob ("*.py" )),
99- ids = lambda p : p .name ,
100- )
101104def test_api_examples (example ):
102105 """Test API-level examples (no napari, no matplotlib)"""
103106 runpy .run_path (str (example ), run_name = "__main__" )
104107
105108
106- @pytest .mark .parametrize (
107- "example" ,
108- sorted ((EXAMPLES / "cli" ).glob ("*.sh" )),
109- ids = lambda p : p .name ,
110- )
111109def test_cli_examples (example , tmp_path , monkeypatch ):
112110 """Test CLI-level shell script examples (skip 'wo view' lines)."""
113111 import shlex
0 commit comments