sebastianbergmann/php-code-coverage
71.3
Strong · 26 September 2026
17.9k
lines of production code
PHP
primary language
4
measurements over time
What this system is
This system is a PHP code coverage library that collects and analyzes execution data from Xdebug and PCOV drivers. It processes raw coverage metrics into typed data structures, supporting granular analysis of lines, branches, and paths, as well as filtering by test size. The library generates structured reports in multiple formats, including HTML with class-oriented views and control flow graphs, JSONL, and various XML standards like Cobertura and OpenClover.
How it got here
2009–2016 — modernization and driver refactoring
20 changes.
The project underwent a comprehensive architectural overhaul, introducing a new Driver abstraction to support PCOV and Xdebug 3.1+ while removing legacy PHP\_CodeCoverage and Xdebug 2 support. This period saw the complete redesign of the HTML reporting engine to eliminate external dependencies, add tabbed views for branch and path coverage, and implement strict typing throughout the codebase.
2019–2024 — Data model refactoring and test expansion
19 changes.
The codebase underwent a significant architectural shift, replacing raw arrays with typed value objects to support per-test hit counts and improving static analysis caching reliability. This structural overhaul was accompanied by a massive expansion of the test suite, adding comprehensive coverage for data processing, report generation, and static analysis components.
2025–2026 — HTML class view and JSONL reporter
25 changes.
This period focused on introducing a new class-oriented HTML report view that organizes coverage metrics by class hierarchy and supports filtering by test size. It also added a new JSONL reporter for structured output and enhanced static analysis accuracy for dead code detection. Comprehensive test suites and fixtures were added to validate these new reporting features and serialization infrastructure.
Features
HTML report now supports filtering by test size and visualizing path coverage
The HTML code coverage report now includes a filter that allows users to view coverage metrics broken down by test size (Small, Medium, Large), with the UI dynamically updating to show or hide buttons for sizes that lack data. Additionally, the report now visualizes path coverage using control flow graphs (rendered via Graphviz) for each method, and clicking a path in the source view highlights the corresponding edges in the graph. These changes are implemented in the new \ControlFlowGraph\ and \Renderer\ classes and their associated JavaScript, replacing the previous Bootstrap/JQuery dependencies with a standalone, theme-aware design.
src/Report/Html · high confidence
Initial JSONL code coverage reporter
A new JSONL reporter has been added to the code coverage reporting suite. This feature introduces a \Facade\ class that processes code coverage data and writes it into two separate JSON Lines files (\coverage.jsonl\ and \tests.jsonl\) alongside a \meta.json\ file. The implementation handles encoding JSON through a helper that throws exceptions from the package's own exception hierarchy, ensuring consistent error handling for write operations and JSON serialization.
src/Report/Jsonl · high confidence
Initial class-oriented HTML report view
Adds a new HTML report builder that generates a hierarchical class view, organizing classes and traits into a namespace tree. The builder processes static analysis data to construct nodes for classes and their associated traits, enabling users to visualize code structure and inheritance relationships in the generated HTML coverage reports.
src/Report/Html/ClassView · high confidence
Introduce class-oriented HTML report view
Adds a new class-oriented view to the HTML code coverage report, providing dedicated dashboard, namespace, and class pages that display coverage metrics, bubble charts, and Crap index tables organized by class hierarchy rather than file structure.
src/Report/Html/ClassView/Renderer · high confidence
Introduce class-oriented HTML report with deduplicated namespace metrics
The HTML code coverage report now includes a class view that aggregates metrics at the namespace level, ensuring that each class's own code and each trait's code is counted exactly once even when shared across multiple classes. This new view also supports filtering by test size (unit, integration, etc.), allowing users to analyze coverage based on specific test categories.
src/Report/Html/ClassView/Node · high confidence
New XML coverage report formats: Cobertura and OpenClover
The report generation module now includes dedicated exporters for the Cobertura and OpenClover XML formats, in addition to the existing Clover support. The new Cobertura reporter produces XML compliant with the Cobertura schema, including line and branch rates, while the OpenClover reporter generates XML that validates against the OpenClover schema definition. These additions allow users to integrate code coverage data directly with CI/CD tools and dashboards that expect these specific XML structures.
src/Report · high confidence
Version 14.4.0 introduces JSONL reporting and unfiltered coverage collection
This release adds a new JSONL reporter that writes \meta.json\, \coverage.jsonl\, and \tests.jsonl\ files to a directory, providing structured coverage data including branch coverage details and test-to-line mappings. It also introduces \enableCollectionOfDataNotFilteredUsingTargets()\ and \dataNotFilteredUsingTargets()\ methods to the \CodeCoverage\ class, allowing users to collect coverage data that is not filtered using code coverage targets. The release also includes updated build automation, PHPStan configuration (level 10), and PHP-CS-Fixer settings.
(repo-wide) · high confidence
Removals
Removal of legacy PHP\_CodeCoverage class
The legacy \PHP\_CodeCoverage\ class has been removed from the codebase. This change eliminates the old implementation that wrapped Xdebug's code coverage functionality, marking the end of support for this specific class structure in favor of the current architecture.
PHP · high confidence
Behavioural changes
161 commits (1 fix) modifying tools
A change to existing behaviour in tools — 161 commits (1 fix), 4 files.
tools · medium confidence · unverified
Automated release notes extraction and HTML report expectation regeneration
Build scripts now include a tool to extract version-specific release notes from the changelog for automated release creation, and a script to regenerate HTML report test expectations. The expectation script ensures test stability by replacing volatile data (versions, dates, paths) with placeholders and handling Graphviz dependency variations, while also covering new scenarios like class views with traits and inheritance.
build/scripts · high confidence
Code coverage data is now represented by typed objects with per-test hit counts
The internal data structures for code coverage in src/Data have been refactored from raw arrays to dedicated value objects (HitMap, ProcessedBranchCoverageData, ProcessedPathCoverageData, ProcessedClassType, ProcessedFunctionType, ProcessedMethodType, ProcessedTraitType, and RawCodeCoverageData). This change enables the system to record and report how many times each test case executed a specific line, branch, or path, rather than just a binary executed/not-executed status. Additionally, test case identifiers are interned to integer indexes to reduce memory usage and improve performance when merging coverage data.
src/Data · high confidence
Code coverage reporting engine refactored with new data structures and report facade
The code coverage engine has been significantly refactored to improve type safety, performance, and report generation. Raw coverage data is now encapsulated in dedicated value objects like ProcessedFunctionCoverageData, and a new Granularity enum standardizes line, branch, and path coverage levels. A new Report\\Facade provides a unified entry point for generating HTML, XML, JSONL, Clover, and Crap4j reports, while the HTML report itself has been redesigned to remove Bootstrap and jQuery dependencies in favor of server-side rendered SVG charts and a configurable, colorblind-friendly color scheme. Additionally, a new PcovDriver has been added to support the PCOV extension, and the FilterProcessor now handles complex filtering logic including intentional coverage checks and executable line analysis.
phpunit/php-code-coverage · high confidence
HTML report renderer rewritten with tabbed line, branch, and path coverage views
The HTML code coverage report now supports separate, tabbed views for line, branch, and path coverage within individual file reports. The \File\ renderer generates distinct HTML files for each coverage type (e.g., \\_branch.html\, \\_path.html\) when that data is available, allowing users to switch between granular views. The \Dashboard\ renderer has been updated to display server-side rendered SVG bubble charts and CRAP (Change Risk Anti-Patterns) tables for classes and methods, replacing the previous client-side charting approach. Additionally, the \Directory\ renderer now provides a structured listing of files and subdirectories with aggregated coverage statistics.
src/Report/Html/Renderer · high confidence
Improved static analysis for dead code and executable lines
The static analysis engine now more accurately identifies dead code and executable lines in coverage reports. It detects unreachable code following exhaustive if/else, match, and switch statements, as well as after infinite loops, and correctly ignores lines containing only attributes. Additionally, it avoids marking default parameter values of abstract methods as executable, leading to more precise coverage metrics.
src/StaticAnalysis/Visitor · high confidence
New Driver abstraction with Xdebug 3.1+ requirement and granular coverage control
The code coverage subsystem introduces a new \Driver\ interface and a \Selector\ to automatically choose between PCOV and Xdebug drivers based on the requested coverage granularity (line, line+branch, or line+branch+path). The Xdebug driver now strictly requires Xdebug 3.1 or later, enforcing the new \xdebug\_info('mode')\ API for coverage activation and removing support for Xdebug 2 and PHPDBG. This change allows users to explicitly request branch and path coverage, with the driver handling the necessary Xdebug flags and data parsing internally.
src/Driver · high confidence
New exception hierarchy for code coverage operations
The \src/Exception\ directory now introduces a dedicated \Exception\ interface that all library exceptions implement, providing a unified way to catch errors specific to this package. A comprehensive set of new exception classes has been added to handle specific failure scenarios, including driver availability issues (e.g., \XdebugNotAvailableException\, \PcovNotAvailableException\), serialization and merging errors (e.g., \VersionMismatchException\, \DriverMismatchException\, \EmptyPathListException\), and coverage target validation (e.g., \InvalidCodeCoverageTargetException\). This change allows users to catch and handle precise error conditions during code coverage collection, serialization, and report generation.
src/Exception · high confidence
Redesigned HTML report with configurable themes and no external dependencies
The HTML code coverage report has been completely redesigned to remove dependencies on Bootstrap and jQuery, relying instead on a standalone, dependency-free stylesheet. This change introduces support for automatic light and dark mode themes and allows coverage-related colors (such as success, warning, and danger states) to be fully configured via CSS custom properties. Users will see a modernized interface with improved readability, including better icon contrast in dark mode and consistent styling across breadcrumbs, tabs, and layout elements, all driven by the new CSS variables defined in the template.
src/Report/Html/Renderer/Template/css · high confidence
Redesigned HTML report with tabbed branch/path views and CRAP metrics
The HTML coverage report templates have been completely rewritten to support a fluid layout and tab-based navigation between line, branch, and path coverage views. The new class, file, directory, and dashboard pages now include dedicated columns for branch and path coverage metrics alongside the existing line and method data, and display the CRAP (Change Risk Anti-Patterns) index in the table headers and dashboard charts. The dashboard specifically features server-side rendered SVG bubble charts and CRAP tables, while the file and class views use a view switcher to toggle between coverage types.
src/Report/Html/Renderer/Template · high confidence
Refactored code coverage node classes with strict typing and test-size filtering support
The Node layer (AbstractNode, Directory, File, Iterator) has been rewritten to use strict scalar type declarations, readonly properties, and final classes. This refactoring introduces support for filtering code coverage by test size, allowing users to see how often a line was executed by specific test categories (e.g., small vs. large tests). The File node now tracks hit counts and test-size-specific execution data, while Directory and AbstractNode provide updated methods to calculate percentages and counts based on this granular data. The changes also improve performance by reducing redundant file parsing and resolving test sizes only once per report.
src/Node · high confidence
Refactored code coverage utilities and fixed path reduction bug
The code coverage utilities in src/Util have been reorganized into dedicated classes: EnsuresUtf8 handles character encoding normalization, Filesystem provides safe directory creation and file writing, Phar detects PHAR bundling, and PhpParserVersion manages caching based on the nikic/php-parser version. Additionally, PathReducer now correctly handles single-file coverage by renaming files to their basenames only when the path actually changes, fixing a bug where identical old and new paths would corrupt coverage data.
src/Util · high confidence
Refactored static analysis caching and file analysis architecture
The static analysis subsystem has been restructured to improve cache reliability and isolation. A new CachingSourceAnalyser now generates cache keys based on content hashes, the library version, and the specific PHP-Parser version, ensuring that cached results are invalidated when the parser changes. The FileAnalyser class now handles in-memory caching and tracks parse errors, while the Registry ensures that static analysis results are not shared between differently configured CodeCoverage objects, preventing cache contamination across different test runs.
src/StaticAnalysis · high confidence
XML coverage report generation refactored with strict typing and new structure
The XML coverage report generation logic has been significantly refactored to improve performance and code quality. The new implementation uses strict scalar type declarations and final classes for internal components like Directory, File, and Facade. It replaces the previous DOM-based approach with XMLWriter for faster output generation and introduces a new Facade class to orchestrate the report creation process. Build information is now included in the XML output, and the system supports an option to exclude source code from the report. Additionally, the code handles I/O errors more robustly and ensures UTF-8 encoding for all file names.
src/Report/Xml · high confidence
php-code-coverage 14.4.0 released
This release updates the library to version 14.4.0. The diff shows the introduction of new source files for the core \CodeCoverage\ class, the \Filter\ class (which now includes caching for file existence checks), and a \Version\ class that reports the version string. This represents a version bump and structural reorganization of the library's source code.
src · high confidence
Test coverage
Add test bootstrap file for environment setup; Added Cobertura XML test fixtures and DTD schema; Added end-to-end test fixtures for class view with traits and inheritance; Added test coverage for code-coverage core components; Added test coverage for code-coverage target mapping and validation; Added test expectations for HTML coverage report with test-size filtering; Added test expectations for HTML report path coverage of namespaced source; Added test fixture files for filter tests; Added test fixtures for HTML coverage reports of classes with anonymous functions; Added test fixtures for OpenClover XML reporter; Added test fixtures for class and facade analysis; Added test fixtures for class coverage with traits and inheritance; Added test fixtures for class targeting scenarios; Added test fixtures for filesystem-based code coverage targets; Added test fixtures for path coverage HTML reports; Added test fixtures for the class-oriented HTML report view; Added test infrastructure for code coverage analysis; Added tests for class-oriented HTML report node components; Added tests for code coverage report generators and facade; Added tests for code coverage serialization, unserialization, and merging; Added tests for static analysis caching and registry behavior; Added tests for static analysis visitors; Added tests for the HTML ClassView Builder; Added tests for the JSONL coverage reporter; Added tests for the class-oriented HTML report renderer; Added tests for the redesigned HTML coverage report; Added tests for the redesigned class-oriented HTML coverage report; Added unit tests for PCOV and Xdebug code coverage drivers; Added unit tests for TestSizes bitmask logic; Added unit tests for code coverage data processing classes; Added unit tests for code-coverage exception classes; Added unit tests for code-coverage utility classes; Added unit tests for static analysis value objects; Added unit tests for the code-coverage Node component; Expanded test fixtures for PHP 8.2+ coverage analysis; Updated HTML coverage report test fixtures; Updated HTML report test fixtures for ignored lines; Updated class-oriented HTML report test fixtures.
Dependencies
Added PHPStan stubs for pcov and xdebug extensions
A new stub file for the pcov and xdebug extensions has been added to the PHPStan configuration, providing type definitions for functions such as pcov\\waiting, pcov\\collect, xdebug\_info, and xdebug\_get\_code\_coverage. This addition supports the project's static analysis setup by defining the signatures and return types for these code-coverage-related functions, ensuring PHPStan can correctly analyze code that interacts with these extensions.
build/phpstan-stubs · high confidence
Update dependencies and lock PHPStan tooling versions
The project's \composer.json\ has been updated to require PHP 8.4 or higher and bumped several runtime dependencies, including \nikic/php-parser\ to ^5.9.0, \sebastian/environment\ to ^9.3.2, \sebastian/lines-of-code\ to ^5.0.2, and \theseer/tokenizer\ to ^2.0.1. Development dependencies now target \phpunit/phpunit\ ^13.3.4. Additionally, the PHPStan tooling configuration in \tools/.phpstan/composer.json\ has been updated to use \phpstan/phpstan\ ^2.2.15 along with its associated extensions (\phpstan-phpunit\, \phpstan-strict-rules\, \ergebnis/phpstan-rules\), and the corresponding lock file has been regenerated to reflect these specific versions.
(dependencies) · high confidence
Updated PHPStan static analysis tooling to version 2.2.15
The local PHPStan installation in tools/.phpstan has been updated to version 2.2.15, along with its extensions phpstan-strict-rules (2.0.12), phpstan-phpunit (2.0.18), and ergebnis/phpstan-rules (2.14.0). This upgrade brings stricter static analysis rules and improved type coverage for the project's codebase.
tools/.phpstan · high confidence
Written by watchdog.canine.dev from the codebase's own history, inside the signed delivery this page is composed from.
How this codebase got here
Score
- CAI 53 → 71 (+17.9)
- Rubric changed (rubric-2026.08.15 → rubric-2026.09.15) — scores are not directly comparable.
Lenses
- Code Health 89 → 81 (-8.7)
- Architecture 96 → 94 (-1.9)
- Maturity 59 → 62 (+2.6)
- Readiness 32 → 74 (+42.3)
- Security 81 → 89 (+8.0)
Resolved (18)
- Coverage not measured — test suite did not build
- Dimension evaluation failed
- Duplicated block (12 lines × 2) (src/Report/Html/Renderer/File.php)
- Duplicated block (13 lines × 2) (src/Report/Html/Renderer/File.php)
- Duplicated block (5 lines × 3) (src/Node/File.php)
- Duplicated block (6 lines × 2) (src/Node/File.php)
- Duplicated block (6 lines × 2) (src/Report/Clover.php)
- Duplicated block (6 lines × 2) (src/Report/OpenClover.php)
- Duplicated block (6 lines × 3) (src/Test/Target/MapBuilder.php)
- Duplicated block (7 lines × 2) (src/Report/Cobertura.php)
- Duplicated block (7 lines × 3) (src/Report/Html/Renderer.php)
- Duplicated block (8 lines × 2) (src/Report/Cobertura.php)
- Duplicated block (8 lines × 2) (src/Serialization/Unserializer.php)
- Duplicated block (9 lines × 2) (src/Report/Cobertura.php)
- No exposed public API
- No tests found
- Test reliability not included
- The Usage section covers collecting data and generating an OpenClover report but omits how to generate a JUnit or HTML test-report output from serialized coverage. (README.md)
New (136)
- (anonymous) (cognitive 18) (src/Report/Html/Renderer/Template/js/source-view.js)
- (anonymous) (cognitive 22) (src/Report/Html/Renderer/Template/js/coverage-table.js)
- (anonymous) (cyclomatic 18) (src/Report/Html/Renderer/Template/js/source-view.js)
- (anonymous) (cyclomatic 19) (src/Report/Html/Renderer/Template/js/coverage-table.js)
- Ambiguous scope of 'clear'. CodeCoverage.clear() likely clears the entire coverage state (data, tests, etc.), while RawCodeCoverageData.clear() likely clears the raw data buffer. While the types differ, the verb 'clear' is overloaded. CodeCoverage also has clearCache(), which is distinct, but clear() vs clearCache() vs clear() on data objects creates a slight naming collision in intent (reset state vs clear cache vs clear buffer).
- Boundary-crossing change coupling: File.php ↔ FileAnalyser.php (src/Node/File.php)
- Builder.collectRegistries (cognitive 17) (src/Report/Html/ClassView/Builder.php)
- Change coupling: Clover.php ↔ Crap4j.php (src/Report/Clover.php)
- Change coupling: Crap4j.php ↔ Facade.php (src/Report/Crap4j.php)
- ClassTooLong: File (src/Report/Html/Renderer/File.php)
- Class_.renderSourceSection (cognitive 41) (src/Report/Html/ClassView/Renderer/Class_.php)
- Class_.renderSourceSection (cyclomatic 18) (src/Report/Html/ClassView/Renderer/Class_.php)
- Clover.process (cognitive 56) (src/Report/Clover.php)
- Clover.process (cyclomatic 22) (src/Report/Clover.php)
- Cobertura.process (cognitive 59) (src/Report/Cobertura.php)
- Cobertura.process (cyclomatic 24) (src/Report/Cobertura.php)
- CodeCoverage.append (cognitive 19) (src/CodeCoverage.php)
- CodeCoverage.append (cyclomatic 19) (src/CodeCoverage.php)
- ControlFlowGraph.buildEdgePathClasses (cognitive 26) (src/Report/Html/ControlFlowGraph.php)
- ControlFlowGraph.generateDot (cognitive 30) (src/Report/Html/ControlFlowGraph.php)
- …and 116 more
Changes since last survey
- 94 commits — 89 feature/other, 5 fixes
By area
- (root) — 21 commits
- tools/.phpstan — 21 commits
- (repo) — 19 commits
- src/Report — 8 commits
- .github/workflows — 6 commits
- tests/tests — 6 commits
- tests/_files — 5 commits
- .phive/phars.xml — 2 commits
- src/Data — 2 commits
- src/CodeCoverage.php — 1 commit
- src/Node — 1 commit
- src/StaticAnalysis — 1 commit
- src/Util — 1 commit
Notable commits
- fix: Fix CS/WS issues
- fix: Fix CS/WS issues
- fix: Fix alignment and width of Paths and Branches lines in text report summary
- fix: Fix return type of Directory::getIterator() reported by PHPStan 2.2.14
- fix: More alignment fixes
- change: Allow collection of code coverage data that is not filtered using code coverage targets
- change: Assign the whole branch when normalizing Xdebug back-edge branches
- change: Closes #1305
- change: Closes #1314
- change: Closes #1331
- change: Closes #1335
- change: Disable test size filter buttons for test sizes that have no coverage data
- change: Do not call sprintf(), explode(), and trim() for every token when highlighting source code
- change: Do not collect only line coverage when branch coverage is requested and Xdebug is used
- change: Do not count the paths of a closure and the paths of its enclosing function as the same paths
- change: Do not depend on tomasvotruba/type-coverage
- change: Do not escape the popover markup of a test again for every line that test covers
- change: Do not perform lock-file maintenance
- change: Do not rename a file to its own name when reducing paths for a single covered file
- change: Do not treat default values of parameters of abstract methods as executable
- …and 74 more
Architecture
- Containers 0 added · 0 removed · contexts 1 added · 0 removed · edges 0 added · 0 removed
Added bounded contexts (1)
- phpunit/php-code-coverage
Written by watchdog.canine.dev from the codebase's own history, inside the signed delivery this page is composed from.
Survey your own repository
sebastianbergmann/php-code-coverage was measured the same way every project in this corpus was: the same rubric, at a pinned commit, with the result published in full. Point a surveyor at a repository you know and see whether you agree with it.
About this page
- The score is its most recent published measurement, taken on 26 September 2026 at a pinned commit. It is not a live figure and does not change until the project is measured again.
- Measured at commit 9b94a0328227df891482a39d7588e15a18e660cd — the exact code this score is about.
- Scored under rubric-2026.09.15 — the same rubric and the same method as every other entry in this index.
- Measured by watchdog.canine.dev using codehealth-analyzer preprod-a15879f6f801.