Skip to content

S003: Coverage Readers

FieldValue
SpecS003
FeatureCoverage Readers
Date2026-04-23
StatusDraft
Authorspec-writer-agent

Overview

The Coverage Readers module is responsible for ingesting pre-generated XML coverage reports and normalizing them into a uniform data structure that downstream rules and the CLI can consume. Parity never executes tests; it reads existing coverage files produced by language-native test and coverage tools.

Three coverage formats are supported: Clover XML (a single file with per-file statement coverage), Cobertura XML (a portable single-file format used by many ecosystems), and PHPUnit XML (a directory of per-class XML files with per-line, per-test attribution). The format is detected automatically based on whether the configured path points to a file or a directory containing index.xml. When multiple paths are configured, the first existing match wins.

The data produced by these readers feeds directly into the rules system (S002). Clover and Cobertura XML provide enough data for the minimum-coverage rule. PHPUnit XML additionally enables matched-coverage, coverage-attribution, and the --show-tests CLI flag (S001) by exposing which specific test methods covered each line of each source file.

User Scenarios

S003-US-001 [P1] As a developer running parity check, I want per-file coverage percentages read from my Clover XML report so that the minimum-coverage rule can evaluate each source file.

S003-US-002 [P1] As a developer using PHPUnit XML coverage, I want per-test attribution data so that matched-coverage can distinguish coverage from the matching test vs. incidental coverage from other tests.

S003-US-003 [P2] As a CI pipeline operator, I want Parity to auto-detect the coverage format from the configured path so that I do not need to specify the format explicitly.

S003-US-004 [P2] As a developer, I want to configure multiple fallback coverage paths so that PHPUnit XML is used when available and Clover XML is used as a fallback.

S003-US-006 [P1] As a developer in a non-PHP ecosystem, I want to use Cobertura XML so that Parity can enforce per-file coverage for JavaScript, TypeScript, Rust, Python, Go, and other projects that commonly emit Cobertura.

S003-US-005 [P1] As a developer, I want clear error messages when coverage files are missing or malformed so that I can diagnose CI pipeline issues quickly.

Requirements Summary

IDTypePriorityTitleStatus
S003-FR-001FunctionalP1Clover XML per-file coverage readingDraft
S003-FR-002FunctionalP1Clover XML global coverage readingDraft
S003-FR-003FunctionalP1Path normalization with project rootDraft
S003-FR-004FunctionalP1PHPUnit XML directory readingDraft
S003-FR-005FunctionalP1PHPUnit XML per-file coverageDraft
S003-FR-006FunctionalP1PHPUnit XML per-test attributionDraft
S003-FR-007FunctionalP1PHPUnit XML per-line coverage mappingDraft
S003-FR-008FunctionalP1PHPUnit XML executable line countsDraft
S003-FR-009FunctionalP1PHPUnit XML global coverage percentageDraft
S003-FR-010FunctionalP1Format auto-detectionDraft
S003-FR-011FunctionalP1Multi-path fallback resolutionDraft
S003-FR-012FunctionalP1Error handling for missing filesDraft
S003-FR-013FunctionalP1Error handling for malformed XMLDraft
S003-FR-014FunctionalP2Source prefix extraction from PHPUnit XMLDraft
S003-FR-015FunctionalP2Dual-key lookup (absolute + relative)Draft
S003-FR-016FunctionalP1Zero-statement files default to 100%Draft
S003-FR-017FunctionalP1Cobertura XML per-file coverage readingDraft
S003-FR-018FunctionalP1Cobertura XML global coverage readingDraft
S003-IF-001InterfaceP1CoverageReader.read() signature and return typeDraft
S003-IF-002InterfaceP1CoverageReader.readGlobalCoverage() signatureDraft
S003-IF-003InterfaceP1PhpUnitXmlCoverageReader.read() signature and return typeDraft
S003-IF-004InterfaceP1Clover XML schema contractDraft
S003-IF-005InterfaceP1PHPUnit XML schema contractDraft
S003-IF-006InterfaceP1Normalized output consumed by CheckCommandDraft
S003-AS-001AcceptanceP1Read Clover XML happy pathDraft
S003-AS-002AcceptanceP1Read PHPUnit XML happy pathDraft
S003-AS-003AcceptanceP1Format auto-detection selects correct readerDraft
S003-AS-004AcceptanceP1Multi-path fallback selects first existingDraft
S003-AS-005AcceptanceP1Per-test attribution populates testsByFileDraft
S003-AS-006AcceptanceP2Source prefix prepended to relative pathsDraft
S003-AS-007AcceptanceP1Missing coverage file returns empty/nullDraft
S003-AS-008AcceptanceP1Malformed XML returns empty/nullDraft
S003-AS-009AcceptanceP1Global coverage from Clover project metricsDraft
S003-AS-010AcceptanceP1Global coverage from PHPUnit XML root directoryDraft
S003-AS-011AcceptanceP1Read Cobertura XML happy pathDraft
S003-EC-001Edge CaseP1Coverage file does not existDraft
S003-EC-002Edge CaseP1Coverage file is not readable (permissions)Draft
S003-EC-003Edge CaseP1XML is malformed / not valid XMLDraft
S003-EC-004Edge CaseP1Clover file element with no metrics childDraft
S003-EC-005Edge CaseP1Clover file element with empty name attributeDraft
S003-EC-006Edge CaseP1Zero statements in a fileDraft
S003-EC-007Edge CaseP1PHPUnit XML directory missing index.xmlDraft
S003-EC-008Edge CaseP1PHPUnit XML file node with empty hrefDraft
S003-EC-009Edge CaseP2PHPUnit XML referenced file does not exist on diskDraft
S003-EC-010Edge CaseP2PHPUnit XML coverage line with no nr attributeDraft
S003-EC-011Edge CaseP2PHPUnit XML covered element with empty by attributeDraft
S003-EC-012Edge CaseP2No coverage candidates found at any configured pathDraft
S003-EC-013Edge CaseP2Windows-style backslash paths in XMLDraft
S003-EC-014Edge CaseP2Relative paths in Clover XML without project rootDraft
S003-EC-015Edge CaseP2Project source attribute missing from PHPUnit XMLDraft
S003-EC-016Edge CaseP1All configured paths are missingDraft
S003-SC-001SuccessP1Clover reader produces correct per-file percentagesDraft
S003-SC-002SuccessP1PHPUnit XML reader produces correct per-file percentagesDraft
S003-SC-003SuccessP1PHPUnit XML reader produces correct per-test attributionDraft
S003-SC-004SuccessP1Format detection is deterministic and correctDraft
S003-SC-005SuccessP1No exceptions propagated to CLI on bad inputDraft
S003-SC-006SuccessP1Cobertura reader produces correct per-file and global percentagesDraft

Cross-Spec Dependencies

  • Depends on: S006 (Configuration -- coverage_xml path list, min_coverage_global)
  • Required by: S002 (Rules System -- minimum-coverage, matched-coverage, coverage-attribution rules consume the coverage data structures produced here)
  • Required by: S001 (CLI Commands -- --show-tests flag relies on testsByFile from PHPUnit XML reader)
  • Required by: S004 (Coverage Linkers -- consumes per-line coverage data for linking)