Fix coverage double-counting (src/ vs installed package)#22
Merged
Conversation
CI installs the package non-editably (to compile the C++ extension), so imports resolve to site-packages while --cov=src separately measured the untouched src/ tree at 0% — doubling the denominator and roughly halving reported coverage (~93% -> ~50%). Measure a single source (--cov=error_align) and add [tool.coverage.paths] to merge the src/ and site-packages copies into one logical path. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #22 +/- ##
===========================================
+ Coverage 50.47% 93.31% +42.83%
===========================================
Files 14 9 -5
Lines 1369 658 -711
Branches 229 106 -123
===========================================
- Hits 691 614 -77
+ Misses 651 17 -634
Partials 27 27 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Contributor
There was a problem hiding this comment.
Pull request overview
Updates the project’s pytest/coverage configuration to prevent coverage double-counting when tests execute the installed error_align package (in site-packages) while also tracking the src/ tree.
Changes:
- Switch pytest coverage collection from
--cov=srcto--cov=error_alignto avoid measuring an unexecutedsrc/copy at 0%. - Add Coverage.py path-mapping in
pyproject.tomlto unifysrc/error_alignand*/site-packages/error_aligninto a single logical source location.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| pytest.ini | Updates default pytest addopts to measure only error_align (not src). |
| pyproject.toml | Adds Coverage.py path mapping (and run source) intended to merge editable/non-editable install paths. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
The baselines/ modules (POWER, etc.) are optional and largely untested. They only started counting toward coverage when rapidfuzz became a core dependency (#21), since that made error_align.baselines importable in CI — dropping reported coverage from ~93% to ~50%. The codecov.yml ignore glob ("src/error_align/baselines/*") never matched their installed path ("error_align/baselines/..."), so they slipped through. Omit them at the coverage layer (source-independent) and fix the codecov ignore glob to match any baselines path. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
.coveragerc takes precedence over pyproject.toml, so the [tool.coverage.*] config added earlier was silently ignored — two configs that could diverge. Remove it and keep .coveragerc as the single source of truth. Also fix its omit glob: src/error_align/baselines/* only matched the editable layout, so in CI (site-packages) baselines were not omitted by coverage.py and were excluded only by the codecov ignore. Use */baselines/* to match both. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Robert James (rjames-0)
approved these changes
Jun 23, 2026
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.
Problem
After #21, reported coverage dropped from ~93% to ~50%. This is a measurement artifact, not a real loss of test coverage.
The CI coverage table lists every module twice: the executed copy under
…/site-packages/error_align/*(real coverage) and an untouched copy undersrc/error_align/*reported at 0%. The phantomsrc/copy has the same statement count as the real package with all statements missed, so it doubles the denominator while hits stay flat — mechanically halving the percentage (645 hit / 645 → 634/1290 ≈ 49%).Root cause
Two coverage sources were tracked at once:
--cov=src(frompytest.ini)--cov=error_align(from the test workflow)poetry run pip install .installs the package non-editably (this is required — it compiles the C++ extension, so it is not redundant). Imports then resolve tosite-packages, while--cov=srckeeps measuring the on-disksrc/tree at 0%. While an editable install dominated, both resolved to the same paths and coverage deduped them; the0.1.0b9 → 0.1.0b10version bump madepip install .actually lay down the non-editable copy (previously a no-op), exposing the double count.Fix
pytest.ini: measure a single source —--cov=error_aligninstead of--cov=src.pyproject.toml: add[tool.coverage.paths]mappingsrc/error_align↔*/site-packages/error_align(plus[tool.coverage.run] source) so the two locations merge into one logical path regardless of editable vs non-editable install.The C++-compiling
pip install .step is left intact.Verification
Local run now shows a single copy per module, TOTAL 94% (non-baseline), 19 passed — no
src/+site-packagesduplication.🤖 Generated with Claude Code