Repository navigation
ci: GitHub Actions workflow + base pipeline unit tests - #4
Merged
Merged
Conversation
- .github/workflows/ci.yml: GitHub Actions CI on push/PR to main - Python 3.13 setup with pip cache - Installs runtime + test dependencies - Runs pytest with coverage, fails under 85% - Uploads coverage to Codecov (optional) - Separate smoke job for end-to-end DiffQEC run - tests/test_pipeline.py: 49 new unit tests for the base pipeline - make_stim_circuit: Z/X memory, no_reset, noise, distance 3/5 - make_qiskit_circuit: qubit/classical bit counts, X/Z memory, reset - stim_to_qiskit: conversion, dense indexing, noise stripping - get_circuit_info: keys, qubit classification disjoint - internal_helpers: get_qubit_lists, get_meas_order, counts_to_measurement_array - extract_syndromes_manual: noiseless, noise, error injection - extract_syndromes (Stim m2d path) - build_emerald_qubit_map: import contract - decode_hardware_results: mwpm default, diffqec path, unknown decoder - main.run_simulation_test - Pipeline integration: end-to-end Stim + Qiskit paths - tests/__init__.py: empty package marker - pytest.ini: pytest config + coverage settings (source paths, omit rules) - requirements.txt: add pytest>=8.0 and pytest-cov>=5.0 Total: 64 tests passing, 86% line coverage (threshold 85% in CI).
Pytest on CI does not add the project root to sys.path by default, so 'import internal_helpers' and 'import surface_code' fail with ModuleNotFoundError. Adding a conftest.py at the project root fixes this for both the test collection and the runtime tests. Local verification: 64 tests pass, 86% coverage maintained.
The conftest.py approach failed because pytest loads test modules (which trigger 'from internal_helpers import *' in surface_code.py) before conftest.py can modify sys.path. Using 'pythonpath = .' in pytest.ini runs before any test collection, so the project root is on sys.path from the start.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Sets up continuous integration via GitHub Actions and adds comprehensive unit tests for the base QEC pipeline. This gives us automatic test runs and coverage reporting on every push and pull request, so we can catch breakage before merge.
What
.github/workflows/ci.yml— GitHub Actions CIpushtomainand everypull_requesttomainubuntu-latesttest: installs runtime + test deps, runspytestwith coverage, fails if under 85%smoke: runspython -m diffqec.smoke_testend-to-endrequirements.txtandpyproject.tomltests/test_pipeline.py— 49 new unit testsOrganized by module:
TestMakeStimCircuit(8 tests): default Z memory, X memory, case-insensitivememoryarg,no_resetflag, noise model application, partial noise keys, distance 5TestMakeQiskitCircuit(9 tests): return type, metadata keys, distance 2/3 counts, X/Z memory, no_reset, depth scaling, noise param ignoredTestStimToQiskit(5 tests): basic conversion, dense contiguous indices, strips noise instructions, measurement order length, raises on unhandled gatesTestGetCircuitInfo(3 tests): expected keys, qubit classification disjoint, distance-3 countsTestGetQubitLists(2 tests): data/anc split, no-coords fallbackTestGetMeasOrder(1 test): order matches circuitTestCountsToMeasurementArray(3 tests): basic conversion, explicit count, truncationTestExtractSyndromesManual(6 tests): noiseless zero detections, output dict keys, shape, error injection, noise model, print summaryTestExtractSyndromesStim(3 tests): detector sampler, noiseless zero, extract_syndromes with raw_measTestBuildEmeraldQubitMap(2 tests): returns dict, import contractTestDecodeHardwareResults(3 tests): mwpm default, diffqec missing model_path raises, unknown decoderTestMainSimulation(2 tests):run_simulation_testruns,mainentrypoint worksTestPipelineIntegration(2 tests): circuit info consistent, stim→qiskit simulationtests/__init__.pyEmpty package marker for
tests/.pytest.initestpaths = testssurface_code,extract_syndromes,internal_helpers,run_on_hardware,diffqectests/,iqm_utils/,benchmarks/,lumi/,main.py,build_emerald_qubit_rotated.pyslowandhardwaremarkers for selective deselectionrequirements.txtpytest>=8.0pytest-cov>=5.0Test results
Coverage report
extract_syndromes.pyinternal_helpers.pydiffqec/denoiser.pydiffqec/diffusion.pydiffqec/syndrome_processor.pysurface_code.pydiffqec/model.pydiffqec/data.pydiffqec/integrate.pyrun_on_hardware.pymain.pyNext steps
When this is merged, every future PR (including the LUMI benchmark) will automatically run the full test suite and report coverage, catching regressions before they reach
main.