Tests - #1
Conversation
- tests/unit: fast isolated tests for every class/function in cbeam.waveguide, cbeam.propagator, and cbeam.FEval - tests/integration: end-to-end tests rewritten from each docs_source example (basicusage, fib, PL, dc, mmi, PL19); full characterizations marked `slow` - pyproject.toml: pytest config (pythonpath=src, markers, filters) - conftest.py: Agg backend, one-time FEval Julia project instantiation - documents a bug found by the suite: Rectangle.nearest_boundary_point writes outx instead of outy in one branch (xfail) Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- FEval.py / FEvalsetup.py: `from juliacall import Pkg` was removed in juliacall >= 0.9.30, which broke `import cbeam` outright on current installs. Get Julia's Pkg through Main instead (works on old and new juliacall). Verified against juliacall 0.9.26 and 0.9.35. - waveguide.py: Rectangle.nearest_boundary_point assigned `outx` twice in the `i==2, x>xmax` branch, so points past the right edge got a point that wasn't on the rectangle. Assign `outy` as the sibling branches do. - tests: the Rectangle case is now a normal regression test (was xfail). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Explains the layout of tests/ (unit + integration), how to run the suite (pytest, the `slow` marker, the src pythonpath / FEval setup), and shows a typical successful run (134 passed). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The integration tests assert on physical invariants with loose tolerances so they survive a mesh / eigenbasis change. This adds a second, stricter layer: a `golden` fixture (tests/conftest.py) records the actual arrays a run produces under tests/integration/_golden/<id>.npz and, on later runs, checks them with np.testing.assert_allclose. CBEAM_GOLDEN=record write the reference set CBEAM_GOLDEN=check (default) compare; a missing file skips the assertion CBEAM_GOLDEN=off no-op Each slow test now also fingerprints its stable numeric outputs: neffs(z) (resampled onto the current z-grid before comparing), sorted channel/mode power spectra, and mode-amplitude magnitudes. The reference set itself is generated from the `tests` branch library and committed separately. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
13 .npz files under tests/integration/_golden/, one per instrumented integration test, recorded with CBEAM_GOLDEN=record against the `tests` branch library (the pre-refactor code path). These are the agreed numerical ground truth; runs on other branches are compared against them. Also drop the per-mode `uf_power` golden check in test_chain_propagator_end_to_end: those 19 modes span one ~19-fold degenerate subspace, so the per-mode power split is gauge-dependent (moves ~5e-2 between eigensolver bases). The physical channel-power spectrum (`channel_out_power`) is stable and stays pinned. Verified: `multi` (working tree) reproduces every pinned quantity to <= 3e-9 abs; the committed merge without the get_19port_positions revert reproduces all but the 19-port compute_neffs scan (~3e-6, mesh-ordering). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
|
Hey Fabio, great to hear from you again. I think the test suite is good idea. Give me a few days to look everything over and try out the new tests.
Jon
From: FabioRossiArcetri ***@***.***>
Sent: Tuesday, September 1, 2026 3:21 AM
To: jw-lin/cbeam ***@***.***>
Cc: Subscribed ***@***.***>
Subject: [EXTERNAL] [BULK] [jw-lin/cbeam] Tests (PR #1)
You don't often get email from ***@***.*** Learn why this is important<https://aka.ms/LearnAboutSenderIdentification>
CAUTION: This email originated from outside of NASA. Please take care when clicking links or opening attachments. Use the "Report Message" button to report suspicious messages to the NASA SOC.
Hi there Jonathan, we met briefly at last SPIE after your talk, if you remember I am developing a jax backend for cbeam and have multi-wavelength simulations in the works.
Before proceeding with any further developments of cbeam, I propose to add this test suite to cbeam, which I guess will help to track any newly introduced bug or numerical accuracy related problems. I heavily relied on Claude to develop this, you are welcome to let me know what you think!
Cheers
Fabio Rossi
More details about the pull-request itself:
Add a test suite (+ two fixes it surfaced)
What this adds
tests/ - 134 tests, split in two layers:
tests/unit/ (124 fast tests) - isolated coverage of every class and helper in cbeam.waveguide (Prim2D/Circle/Rectangle/Prim2DUnion, Prim3D/Pipe/LinearPipe/Box/BoxPipe, the base Waveguide + all pre-defined subclasses), cbeam.propagator (Propagator/ChainPropagator helpers and the full z-invariant solve_at → characterize → propagate → make_field → save/load path), and cbeam.FEval (BVH tree build/query/evaluate/grid/resample/transverse_gradient).
tests/integration/ (10 slow tests) - one per documentation example (basicusage, fib, PL, dc, mmi, PL19), each rewritten as a test. They build a waveguide, characterize it, and propagate a field, asserting on physical invariants (power conservation, mode ordering, matrix (anti)symmetry) rather than mesh-dependent exact numbers. The heavier ones shorten the device from the docs - same numerical code path, fewer z-steps.
pyproject.toml - pytest config: pythonpath = ["src"] (the suite always tests the in-repo code), slow/integration markers, warning filters.
tests/conftest.py - forces the Agg matplotlib backend, instantiates the src/cbeam/FEval Julia project on first run, gives each Propagator a temp save_dir (nothing touches ./data).
docs_source/testing.rst - a documentation page describing the suite, how to run it, and a sample run. Linked into the main toctree. (The built HTML in docs/ is not regenerated here.)
Fixes surfaced while writing the tests
import cbeam was broken on current juliacall. FEval.py / FEvalsetup.py did from juliacall import Pkg, which juliacall ≥ 0.9.30 removed - so import cbeam raised ImportError on any fresh install. Now Julia's Pkg is obtained via Main (jl.seval("import Pkg"); jlPkg = jl.Pkg). Verified on juliacall 0.9.26 and 0.9.35.
Rectangle.nearest_boundary_point bug (waveguide.py): the i==2, x>xmax branch assigned outx twice instead of outx+outy, so points past the right edge got a "boundary" point that isn't on the rectangle. Fixed to match the sibling branches.
How to run
pytest -m "not slow" # unit + light integration, ~30 s
pytest # everything, ~15-20 min
pytest -m slow # only the full characterizations
Results
Run in a clean Conda env (Python 3.12, juliacall 0.9.35, cbeam installed editable):
suite result time
pytest -m "not slow" 124 passed 32 s
pytest -m slow 10 passed 15 min 29 s
total 134 passed, 0 failed
Notes for the reviewer
No behavior change beyond the two fixes above; everything else is additive (tests/, one docs page, pytest config).
docs/ (generated HTML) is intentionally left alone - it's regenerated by the normal Sphinx build.
…________________________________
You can view, comment on, or merge this pull request online at:
#1
Commit Summary
* 0db398d<0db398d> Add unit + integration test suite
* 7a5d7c5<7a5d7c5> Fix findings surfaced by the test suite
* e383525<e383525> docs: add a testing page
File Changes
(22 files<https://github.com/jw-lin/cbeam/pull/1/files>)
* M .gitignore<https://github.com/jw-lin/cbeam/pull/1/files#diff-bc37d034bad564583790a46f19d807abfe519c5671395fd494d8cce506c42947> (8)
* M docs_source/index.rst<https://github.com/jw-lin/cbeam/pull/1/files#diff-a527137ecb45a04913179fcb3587d79dbac8bcb4a4b4131bde0d7dba5f551bbb> (1)
* A docs_source/testing.rst<https://github.com/jw-lin/cbeam/pull/1/files#diff-38d082410095aa213df45dc4355b604d831603907f4540585196d38057d9f0aa> (119)
* M pyproject.toml<https://github.com/jw-lin/cbeam/pull/1/files#diff-50c86b7ed8ac2cf95bd48334961bf0530cdc77b5a56f852c5c61b89d735fd711> (19)
* M src/cbeam/FEval.py<https://github.com/jw-lin/cbeam/pull/1/files#diff-aa723e0213fca5a67f35b2eab8816c36dbd930644bea859bbf678ab1efcd0ed7> (6)
* M src/cbeam/FEvalsetup.py<https://github.com/jw-lin/cbeam/pull/1/files#diff-cf5cf9cae58546e43b54ead90bf8668913cc03fd61cfdbd304a2bd644599ceeb> (6)
* M src/cbeam/waveguide.py<https://github.com/jw-lin/cbeam/pull/1/files#diff-294a759739e9b13a8fd99008844fed8a4c028e83703f2d1614c3d7c95c97de41> (2)
* A tests/README.md<https://github.com/jw-lin/cbeam/pull/1/files#diff-dacac2ebf9792f0d23c0f922a744486ded01901957d5281290925acd89cf83ac> (48)
* A tests/conftest.py<https://github.com/jw-lin/cbeam/pull/1/files#diff-e52e4ddd58b7ef887ab03c04116e676f6280b824ab7469d5d3080e5cba4f2128> (90)
* A tests/integration/test_dicoupler.py<https://github.com/jw-lin/cbeam/pull/1/files#diff-2aabdacf53b3cfaceee730fa77de93dde45f568482272a3bfbc247e836ead339> (94)
* A tests/integration/test_fib.py<https://github.com/jw-lin/cbeam/pull/1/files#diff-cac56130f6eadaae8687540f3460fffaf79022664a14122b65c619d4a5c2edab> (97)
* A tests/integration/test_mmi.py<https://github.com/jw-lin/cbeam/pull/1/files#diff-d0d343c830de44c43f50b6bba00feb373eee9eb2128669711b04cbe580669040> (106)
* A tests/integration/test_photonic_lantern.py<https://github.com/jw-lin/cbeam/pull/1/files#diff-111769c9a03da7b5361a7e085683b0b962ebfb68b8241f435bd084166a18431b> (111)
* A tests/integration/test_pl19.py<https://github.com/jw-lin/cbeam/pull/1/files#diff-171625d8597643f1d37b8e383b9db85052f7d6565aaf8c703efb0f7567183a9a> (88)
* A tests/integration/test_quickstart.py<https://github.com/jw-lin/cbeam/pull/1/files#diff-36cc2918e9e481478a70c762bb17885a517488eb997d6a7455b20943abe142b8> (52)
* A tests/unit/test_feval.py<https://github.com/jw-lin/cbeam/pull/1/files#diff-84c8cbf7ca8a5957449cb9ae3e24e988ece97bd947106520268d62585a991a79> (120)
* A tests/unit/test_misc.py<https://github.com/jw-lin/cbeam/pull/1/files#diff-96ab6c34e9335c808eddfcbf731dd040caf2aa3f6cd39d432eff8b640f7cf8a3> (88)
* A tests/unit/test_prim2d.py<https://github.com/jw-lin/cbeam/pull/1/files#diff-0549e52c9e901a49971232f1b1b77acd26d7ac596c2e411a0aa5ec0491d28c79> (130)
* A tests/unit/test_prim3d.py<https://github.com/jw-lin/cbeam/pull/1/files#diff-95f2f450d7723eb0ccca1dd61682719ac19934199c9e940a967df57216bf16df> (112)
* A tests/unit/test_propagator.py<https://github.com/jw-lin/cbeam/pull/1/files#diff-d05811e1e77a831ee26acaa266cceab1ea1ea96cc390e0680bfee5649e61ca64> (239)
* A tests/unit/test_waveguide.py<https://github.com/jw-lin/cbeam/pull/1/files#diff-2b284e9c5a538d1cd104d03d73330235f67ca292019c0d946009629efef97b7d> (133)
* A tests/unit/test_waveguide_classes.py<https://github.com/jw-lin/cbeam/pull/1/files#diff-3ea1b430f7edbd6f4f61fe4c7aaaf2708b7f353b4864cc522bc8575545cfb449> (192)
Patch Links:
* https://github.com/jw-lin/cbeam/pull/1.patch
* https://github.com/jw-lin/cbeam/pull/1.diff
-
Reply to this email directly, view it on GitHub<#1?email_source=notifications&email_token=AVQZGLJDTPAJ4OMKTPKRGPL5M2PJNA5CNFSNUABEM5UWIORPF5TWS5BNNB2WEL2QOVWGYUTFOF2WK43UF42DIMJRGEYDQNBTGSTHEZLBONXW5KTTOVRHGY3SNFRGKZFFMV3GK3TUVRTG633UMVZF6Y3MNFRWW>, or unsubscribe<https://github.com/notifications/unsubscribe-auth/AVQZGLNI2XUJTX2BV46KWND5M2PJNAVCNFSNUABFKJSXA33TNF2G64TZHM3TGMJYGY4DSOBYHNEXG43VMU5TKMZRGA3DINJRGMY2C5QC>.
Triage notifications, keep track of coding agent tasks and review pull requests on the go with GitHub Mobile for iOS<https://github.com/notifications/mobile/ios/AVQZGLP3PYUXULJZD76I7F35M2PJNA5CNFSNUABEM5UWIORPF5TWS5BNNB2WEL2QOVWGYUTFOF2WK43UF42DIMJRGEYDQNBTGSTHEZLBONXW5KTTOVRHGY3SNFRGKZFFMV3GK3TUVJTG633UMVZF62LPOM> and Android<https://github.com/notifications/mobile/android/AVQZGLPFEVRCIMO4Y4N2K4D5M2PJNA5CNFSNUABEM5UWIORPF5TWS5BNNB2WEL2QOVWGYUTFOF2WK43UF42DIMJRGEYDQNBTGSTHEZLBONXW5KTTOVRHGY3SNFRGKZFFMV3GK3TUVZTG633UMVZF6YLOMRZG62LE>. Download it today!
You are receiving this because you are subscribed to this thread.Message ID: ***@***.***>
|
| @@ -0,0 +1,119 @@ | |||
| testing | |||
There was a problem hiding this comment.
I think the doc will need to be recompiled for the new page to show up.
There was a problem hiding this comment.
I would leave this to you, since small difference in the toolchain used would result in a messy diff (not terrible once the final result is ok, but still not great to see).
There was a problem hiding this comment.
I also have the file workflows/tests.yaml which would trigger the test in CI (every time a pull request is issued), let me know what you think about this. In the next days I will start to deliver pull requests for the jax path and more! Cheers, Fabio
- test_photonic_lantern.py: the 5 outer lantern ports sit on an exact 5-fold rotational symmetry, so a centered LP01 launch should split ~evenly between them. Add an explicit spread check (relative to the golden reference's ~0.3% observed spread, a 15% bound still leaves large margin) on top of the existing loose bounds, which could pass even with a lopsided/asymmetric split. - test_mmi.py: tighten the 3-fold self-image peak count from a 2-4 range to an exact 3, and switch from a hand-rolled local-maxima counter (which can double-count a plateau) to scipy.signal.find_peaks with a minimum sample separation.
Verified against a live run (venv with juliacall/wavesolve/cbeam built from this checkout): the outer-port relative spread comes in well under 1.5%, so this is still a comfortable margin, just a stricter one than the initial 15% bound.
| assert modes.shape[0] == Nmax | ||
| # effective indices come out sorted high -> low | ||
| assert np.all(np.diff(effective_indices) <= 1e-9) | ||
| golden.check("neffs", effective_indices, rtol=1e-6, atol=1e-9) |
There was a problem hiding this comment.
I get a fail here on when running the "not slow" tests. neffs for modes 3,4,5 (LP21a/b and LP02) don't match golden file. This is the only fail out of all the tests, including the slow ones, on my desktop install. Below is the printout from my test run. I was also able to reproduce this behavior on my work laptop. Both are Windows machines.
Probably a result of differences in gmsh install + low resolution of the solve.
E AssertionError:
E Not equal to tolerance rtol=1e-06, atol=1e-09
E neffs: max|delta|=5.052e-06
E Mismatched elements: 3 / 10 (30%)
E Mismatch at indices:
E [3]: 1.441335940415306 (ACTUAL), 1.4413389326193096 (DESIRED)
E [4]: 1.4413345184221822 (ACTUAL), 1.441337124027709 (DESIRED)
E [5]: 1.4408963204385143 (ACTUAL), 1.4409013722926474 (DESIRED)
E Max absolute difference among violations: 5.05185413e-06
E Max relative difference among violations: 3.50603742e-06
E ACTUAL: array([1.444165, 1.442914, 1.442913, 1.441336, 1.441335, 1.440896,
E 1.439905, 1.439904, 1.439898, 1.43976 ])
E DESIRED: array([1.444165, 1.442914, 1.442913, 1.441339, 1.441337, 1.440901,
E 1.439904, 1.439904, 1.439898, 1.43976 ])
@jw-lin
Hi there Jonathan, we met briefly at last SPIE after your talk, if you remember I am developing a jax backend for cbeam and have multi-wavelength simulations in the works.
Before proceeding with any further developments of cbeam, I propose to add this test suite to cbeam, which I guess will help to track any newly introduced bug or numerical accuracy related problems. I heavily relied on Claude to develop this, you are welcome to let me know what you think!
Cheers
Fabio Rossi
More details about the pull-request itself:
Add a test suite (+ two fixes it surfaced)
What this adds
tests/ — 134 tests, split in two layers:
tests/unit/ (124 fast tests) — isolated coverage of every class and helper in cbeam.waveguide (Prim2D/Circle/Rectangle/Prim2DUnion, Prim3D/Pipe/LinearPipe/Box/BoxPipe, the base Waveguide + all pre-defined subclasses), cbeam.propagator (Propagator/ChainPropagator helpers and the full z-invariant solve_at → characterize → propagate → make_field → save/load path), and cbeam.FEval (BVH tree build/query/evaluate/grid/resample/transverse_gradient).
tests/integration/ (10 slow tests) — one per documentation example (basicusage, fib, PL, dc, mmi, PL19), each rewritten as a test. They build a waveguide, characterize it, and propagate a field, asserting on physical invariants (power conservation, mode ordering, matrix (anti)symmetry) rather than mesh-dependent exact numbers. The heavier ones shorten the device from the docs — same numerical code path, fewer z-steps.
pyproject.toml — pytest config: pythonpath = ["src"] (the suite always tests the in-repo code), slow/integration markers, warning filters.
tests/conftest.py — forces the Agg matplotlib backend, instantiates the src/cbeam/FEval Julia project on first run, gives each Propagator a temp save_dir (nothing touches ./data).
docs_source/testing.rst — a documentation page describing the suite, how to run it, and a sample run. Linked into the main toctree. (The built HTML in docs/ is not regenerated here.)
Fixes surfaced while writing the tests
import cbeam was broken on current juliacall. FEval.py / FEvalsetup.py did from juliacall import Pkg, which juliacall ≥ 0.9.30 removed — so import cbeam raised ImportError on any fresh install. Now Julia's Pkg is obtained via Main (jl.seval("import Pkg"); jlPkg = jl.Pkg). Verified on juliacall 0.9.26 and 0.9.35.
Rectangle.nearest_boundary_point bug (waveguide.py): the i==2, x>xmax branch assigned outx twice instead of outx+outy, so points past the right edge got a "boundary" point that isn't on the rectangle. Fixed to match the sibling branches.
How to run
pytest -m "not slow" # unit + light integration, ~30 s
pytest # everything, ~15–20 min
pytest -m slow # only the full characterizations
Results
Run in a clean Conda env (Python 3.12, juliacall 0.9.35, cbeam installed editable):
suite result time
pytest -m "not slow" 124 passed 32 s
pytest -m slow 10 passed 15 min 29 s
total 134 passed, 0 failed
Notes for the reviewer
No behavior change beyond the two fixes above; everything else is additive (tests/, one docs page, pytest config).
docs/ (generated HTML) is intentionally left alone — it's regenerated by the normal Sphinx build.