Skip to content

Bug: merge-cobertura-classes-blends-union-with-primary-methods #478

Description

@drmoisan
  • Work Mode: full-bug

Summary

Merge-CoberturaClassesByFilename unions the class-level <lines> of all <class> elements sharing
a filename correctly, but never merges the corresponding <methods> subtrees. It then recomputes
line-rate over the descendant axis .//lines/line, which sees the correct union plus only the
primary class's method-level lines. The emitted per-file line-rate is therefore a blend of two
different denominators and matches neither. This is distinct from, and additional to, issue #441.

Environment

  • OS/version: n/a (PowerShell post-processing defect, reproducible from committed data)
  • Python version: n/a
  • Command/flags used: scripts/vscode/Invoke-MSTestWithCoverage.ps1 post-processing path
  • Data source or fixture:
    docs/features/active/2026-08-06-quickfiler-high-confidence-queue-init-stall-424/evidence/qa-gates/coverage-final.cobertura.xml

Steps to Reproduce

  1. Inspect Merge-CoberturaClassesByFilename in
    scripts/vscode/Invoke-MSTestWithCoverage.Helpers.ps1, beginning at :167.
  2. Observe the class-level <lines> union at :217-268. It correctly takes max hits per line number
    across every <class> element sharing a filename.
  3. Observe that the <methods> subtrees of the non-primary group members are not merged into the
    primary class element.
  4. Observe the rate recomputation, which selects over the descendant axis .//lines/line. That axis
    matches both the merged class-level <lines> and the unmerged, primary-only <methods>/<method>/<lines>/<line>.
  5. Verify arithmetically against QfcHomeController.Iteration.cs in the committed report: the true
    per-file figure computed from the class-level union alone is 45/56 = 80.36%, while the emitted
    attribute is 0.8625, which is exactly 69/80 - the blended numerator and denominator.
  6. Cross-check the recipe independently: #424's own delta evidence
    (docs/features/active/2026-08-06-quickfiler-high-confidence-queue-init-stall-424/evidence/qa-gates/coverage-delta.2026-08-07T00-48.md:10,41)
    arrived at the class-level-only computation, confirming that the attribute is not the right source.

Expected Behavior

The emitted per-file line-rate should equal the rate computed from the merged class-level <lines>
set alone: distinct line numbers, max hits per number, hit count over total count.

Actual Behavior

The emitted line-rate mixes the merged class-level line set with the primary class's method-level
line set, producing a figure that corresponds to neither the true per-file rate nor any single
class's rate.

Logs / Screenshots

  • Attached minimal logs or screenshot
  • Snippet: QfcHomeController.Iteration.cs - true per-file 45/56 = 0.8036; emitted attribute
    0.8625 = 69/80. Confirmed against scripts/vscode/Invoke-MSTestWithCoverage.Helpers.ps1:167
    (function start) and :217-268 (the correct union). Discovered during preparation research for
    issue Feature: quickfiler-collection-controller-coverage #454 (epic Feature: quickfiler-80-per-file-coverage #136, child F11); full analysis in
    docs/features/active/2026-08-07-quickfiler-collection-controller-coverage-454/research/coverage-harness-contract.md
    section A.

Impact / Severity

  • Blocker
  • High
  • Medium
  • Low

Any consumer reading the per-file line-rate attribute gets a wrong number, and the error is not in
a consistent direction because it depends on how much of a file's coverage sits in the primary class
versus its siblings. Epic #136 gates every one of its fifteen children on a per-file line rate, so an
uncorrected attribute would produce false passes and false failures across the whole epic.

Source

From: docs/features/potential/2026-08-07-merge-cobertura-classes-blends-union-with-primary-methods.md

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions