Skip to content

fix(codecov): populate branch/condition data in Clover reports - #337

Open
rossaddison wants to merge 1 commit into
php-testo:1.xfrom
rossaddison:fix/334-clover-branch-coverage
Open

fix(codecov): populate branch/condition data in Clover reports#337
rossaddison wants to merge 1 commit into
php-testo:1.xfrom
rossaddison:fix/334-clover-branch-coverage

Conversation

@rossaddison

Copy link
Copy Markdown
Contributor

Closes #334.

What was wrong

CloverReport hardcoded conditionals/coveredconditionals to 0 at both file and project level, and never read FileCoverage::$functions at all — even when branch data was genuinely collected (CoverageLevel::Branch/Path via XdebugDriver). Confirmed by contrast with CoberturaReport in this same package, which already consumes that data correctly (branch-rate, condition-coverage).

What this does

  • BranchCoverageAggregator (new, @internal): extracts CoberturaReport's own countBranches()/buildLineBranchMap() into a shared helper, per the suggested scope in the issue, so both report writers reduce FileCoverage::$functions the same one way instead of drifting.
  • CloverReport: now populates conditionals/coveredconditionals (file and project level) from countBranches(), and folds them into elements/coveredelements alongside statements — mirroring how php-code-coverage's own Clover writer sums methods + statements + branches into elements.
  • Per-line output: a line that's a genuine branch decision point (≥2 outgoing edges, from buildLineBranchMap()) now writes type="cond" with truecount/falsecount instead of type="stmt"; ordinary statement lines are unaffected. Since a branch can have more than 2 outgoing edges (a match arm per case), truecount/falsecount are populated as covered/uncovered edge counts rather than a literal true/false pair — documented inline.
  • Tests: 5 new cases in CloverReportTest — conditionals/coveredconditionals filled from branch data, elements including them, a per-line type="cond" case with truecount/falsecount, a single-outgoing-edge branch staying type="stmt" (not a decision point), and the "no branch data at all" Line-level shape keeping every zero at zero (per the issue's explicit ask).

Verification

  • vendor/bin/testo --suite=Codecov/Unit: 136/136 (up from 131).
  • composer psalm: no errors.
  • composer cs:diff: 0 of 4 touched files need fixing.
  • composer rector:ci (dry-run against the touched files): no changes.
  • Full suite under TESTO_CI=1: 2211/2211, excluding 3 pre-existing, unrelated Tests\Bench\Self\BenchAttr timing-sensitive failures reproduced identically on a clean checkout of 1.x before this change.

Assisted-By: Claude Sonnet 5 noreply@anthropic.com

refactor(codecov): extract branch aggregation shared by Clover and Cobertura
test(codecov): cover Clover's new conditionals/type=cond output

CloverReport hardcoded conditionals/coveredconditionals to 0 and never
read FileCoverage::$functions at all, even when branch data was
genuinely collected (CoverageLevel::Branch/Path via XdebugDriver) --
confirmed by contrast with CoberturaReport in this same package, which
already consumed that data correctly. Reported as php-testo#334.

- BranchCoverageAggregator (new, @internal) extracts
  CoberturaReport::countBranches()/buildLineBranchMap() into a shared
  helper, per the issue discussion's suggested scope, so the two
  report writers stop duplicating the same reduction over
  FileCoverage::$functions.
- CloverReport now populates conditionals/coveredconditionals (file and
  project level) from countBranches(), and folds them into
  elements/coveredelements alongside statements, mirroring how
  php-code-coverage's own Clover writer sums methods + statements +
  branches into elements.
- Per-line output: a line that's a genuine branch decision point
  (>=2 outgoing edges, from buildLineBranchMap()) now writes
  type="cond" with truecount/falsecount instead of type="stmt";
  ordinary statement lines are unaffected.
- CloverReportTest: 5 new cases -- conditionals/coveredconditionals
  filled from branch data, elements including them, a per-line
  type="cond" case with truecount/falsecount, a single-outgoing-edge
  branch staying type="stmt" (not a decision point), and the "no
  branch data at all" Line-level shape keeping every zero at zero.

Verified: `vendor/bin/testo --suite=Codecov/Unit` (136/136, up from
131), `composer psalm` (no errors), `composer cs:diff` (0 of 4 files
need fixing), `composer rector:ci` (no changes) -- all against this
PR's own touched files specifically, alongside a full-suite run
(2211/2211 excluding pre-existing, unrelated Bench/Self timing
flakiness under TESTO_CI=1).

Assisted-By: Claude Sonnet 5 <noreply@anthropic.com>
@rossaddison
rossaddison requested a review from a team as a code owner September 13, 2026 22:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

CloverReport discards collected branch/condition coverage (conditionals always 0)

1 participant