End-to-End Testing
July 7, 2026 · View on GitHub
tests/test_e2e_new_modules.py
End-to-end integration tests for the 20 new modules added in March 2026. These tests verify that modules work together as integrated pipelines, not just in isolation.
Running the Tests
# All e2e tests
pytest tests/test_e2e_new_modules.py -v
# Specific pipeline
pytest tests/test_e2e_new_modules.py -v -k "TestOpenSystemPipeline"
# With timing
pytest tests/test_e2e_new_modules.py -v --tb=short --durations=10
# All tests (unit + e2e)
pytest tests/ -v -m "not slow and not hardware"
Test Structure
| Test class | Pipeline | Modules exercised | Tests |
|---|---|---|---|
TestOpenSystemPipeline | Lindblad ↔ MCWF agreement | lindblad, tensor_jump, ancilla_lindblad | 4 |
TestSymmetryPipeline | Z₂ → U(1) → sparse | symmetry_sectors, magnetisation_sectors, translation_symmetry, sparse_hamiltonian | 8 |
TestMultiPlatformPipeline | Compile → export | xy_compiler, circuit_export, ancilla_lindblad | 4 |
TestVariationalPipeline | NQS + param-shift + VQE | nqs_ansatz, param_shift, gpu_batch_vqe, sparse_hamiltonian, contraction_optimiser | 5 |
TestHardwareReadyPipeline | Ancilla → stats → export | ancilla_lindblad, lindblad, tensor_jump | 2 |
TestFullPipeline | Recommend → solve → export | backend_selector, circuit_export, ancilla_lindblad, magnetisation_sectors, sparse_hamiltonian | 4 |
TestBackendDispatchIntegration | Backend switching | backend_dispatch, backend_selector | 3 |
TestPluginRegistryIntegration | Registry → runner | plugin_registry | 2 |
TestCrossModuleConsistency | Shared computation checks | All ED + sparse + open-system modules | 6 |
| Total | 20 modules | 38 |
Pipeline Descriptions
Pipeline 1: Open-System Kuramoto (Lindblad ↔ MCWF)
Modules: lindblad.py, tensor_jump.py, ancilla_lindblad.py
What is tested:
- Lindblad density matrix R(T) and MCWF ensemble R(T) agree within statistical error for the same physical parameters
- Zero-dissipation case produces identical results (no jumps)
- Ancilla circuit compiles correctly for the same system
- All three open-system methods produce valid output
Physical invariant: Lindblad is exact; MCWF converges to Lindblad in the limit of infinite trajectories. Agreement within for 200 trajectories at is expected.
Pipeline 2: Scaling with Symmetry (Z₂ → U(1) → Sparse)
Modules: symmetry_sectors.py, magnetisation_sectors.py,
translation_symmetry.py, sparse_hamiltonian.py
What is tested:
- Z₂ sector eigenvalues reconstruct the full spectrum exactly
- U(1) sector eigenvalues reconstruct the full spectrum exactly
- Z₂ and U(1) find the same ground energy
- Sparse eigsh matches dense eigh
- Sparse within U(1) sector matches dense U(1) sector
- All four methods agree at
- Memory estimates are consistent (full > Z₂ > U(1))
- Translation symmetry ground within full spectrum
Physical invariant: All methods diagonalise the same Hamiltonian. Ground energy must be identical (up to numerical precision). The only difference is computational cost.
Pipeline 3: Multi-Platform Execution (Compile → Export)
Modules: xy_compiler.py, circuit_export.py, ancilla_lindblad.py
What is tested:
- XY-compiled circuit exports to valid QASM
- XY compiler produces circuits with measurable depth
- All export formats (Qiskit, QASM, Quil) are consistent
- Ancilla circuit is QASM-exportable
Physical invariant: All formats represent the same unitary evolution. Format-specific syntax is validated (OPENQASM header, DECLARE in Quil).
Pipeline 4: Variational Ground State (NQS + Param-Shift + Batch VQE)
Modules: nqs_ansatz.py, param_shift.py, gpu_batch_vqe.py,
sparse_hamiltonian.py, contraction_optimiser.py
What is tested:
- RBM VMC energy within 50% of exact (conservative bound — VMC is not guaranteed to converge for all initialisations)
- Parameter-shift VQE reduces energy over iterations
- Batch VQE scan finds energy below mean random
- NQS energy is a variational upper bound (≥ exact)
- Contraction optimiser gives same results as
np.einsum
Physical invariant: Variational principle — VMC/VQE energy exact ground energy. The gap depends on ansatz expressibility and optimisation.
Pipeline 5: Hardware-Ready Open-System Circuit
Modules: ancilla_lindblad.py, lindblad.py, tensor_jump.py
What is tested:
- Build circuit → check stats → export to QASM (full workflow)
- All three open-system methods produce valid output for same system
Physical invariant: Circuit should have qubits, non-zero resets, and be exportable.
Pipeline 6: Full Auto-Solve Pipeline
Modules: backend_selector.py, circuit_export.py,
ancilla_lindblad.py, magnetisation_sectors.py, sparse_hamiltonian.py
What is tested:
recommend_backend→auto_solveconsistency- Solve → export for same system
- Solve open-system → build ancilla circuit
- U(1) sector → sparse eigsh → level spacing analysis
Physical invariant: auto_solve should use the backend recommended by
recommend_backend. Ground energy should be negative for the XY model.
Level-spacing ratio should be between 0.2 and 0.7 (Poisson to GOE range).
Pipeline 7: Backend Dispatch
Modules: backend_dispatch.py, backend_selector.py
What is tested:
- Setting numpy backend then solving works
- All available backends are settable
to_numpy(from_numpy(x))roundtrip preserves data
Pipeline 8: Plugin Registry
Modules: plugin_registry.py
What is tested:
- Qiskit runner from registry produces valid runner
- Custom backend registration and invocation
Cross-Module Consistency Checks
The TestCrossModuleConsistency class verifies shared computation
invariants across multiple modules:
| Test | Invariant |
|---|---|
test_sparse_hermiticity | |
test_sparse_vs_dense_matrix | Sparse and dense Hamiltonians are identical |
test_sparsity_stats_consistent | Stats match actual matrix properties |
test_lindblad_order_parameter_bounded | $0 \leq R(t) \leq 1$ |
test_mcwf_std_decreases_with_trajectories | More trajectories → less noise |
test_all_ed_methods_agree | Full/Z₂/U(1)/sparse give same at |
Module Coverage Matrix
Each row is a test class; columns are the 20 modules. ✓ = directly tested.
| Module | Open | Symm | Multi | Var | HW | Full | Disp | Plug | Cross |
|---|---|---|---|---|---|---|---|---|---|
lindblad | ✓ | ✓ | ✓ | ||||||
tensor_jump | ✓ | ✓ | ✓ | ||||||
ancilla_lindblad | ✓ | ✓ | ✓ | ✓ | |||||
symmetry_sectors | ✓ | ✓ | |||||||
magnetisation_sectors | ✓ | ✓ | ✓ | ||||||
translation_symmetry | ✓ | ||||||||
sparse_hamiltonian | ✓ | ✓ | ✓ | ✓ | |||||
mps_evolution | |||||||||
contraction_optimiser | ✓ | ||||||||
nqs_ansatz | ✓ | ||||||||
jax_nqs | |||||||||
mitiq_integration | |||||||||
param_shift | ✓ | ||||||||
xy_compiler | ✓ | ||||||||
circuit_export | ✓ | ✓ | |||||||
backend_selector | ✓ | ✓ | |||||||
backend_dispatch | ✓ | ||||||||
plugin_registry | ✓ | ||||||||
gpu_batch_vqe | ✓ |
Note: mps_evolution, jax_nqs, and mitiq_integration require
optional dependencies (quimb, JAX, Mitiq) and are tested in their
respective unit test files (test_mps_evolution.py, test_batch3_modules.py,
test_mitiq_integration.py). The e2e tests avoid optional dependencies
to ensure they run on the CI matrix without extras.
Adding New E2E Tests
When adding new cross-module functionality:
- Identify the pipeline (which modules interact)
- Write a test that exercises the full pipeline, not individual functions
- Assert on physical invariants (energy bounds, conservation laws, consistency between methods) rather than implementation details
- Use
_system(n)helper for standard test systems - Keep systems small () for speed — e2e tests should complete in seconds, not minutes
See Also
- Contributing Guide — how to run the full test suite
- Symmetry Sectors — theory behind Pipeline 2
- Lindblad Solver — theory behind Pipeline 1
- Backend Selector — theory behind Pipeline 6