shipmonk/coverage-guard
Enforce PHP code coverage in CI by targeting specific core methods/blocks instead of overall %. Legacy-friendly: enforce only new/changed code via git patch. Lightweight (nikic/php-parser), extensible rules, easy CLI to check PHPUnit Clover reports.
Enforce code coverage in your CI with ease! Not by percentage, but target core functionality.
nikic/php-parserThis tool helps ensure that certain code blocks are covered by tests, typically core methods in Facades, Controllers, and other key areas of your application.
composer require --dev shipmonk/coverage-guard
# Run tests, collect coverage, generate report:
XDEBUG_MODE=coverage vendor/bin/phpunit tests --coverage-filter src --coverage-clover clover.xml
# Verify coverage:
vendor/bin/coverage-guard check clover.xml
In real application, you will probably use phpunit.xml to configure PHPUnit coverage:
<coverage processUncoveredFiles="true">
<include>
<directory>src</directory>
</include>
<report>
<clover outputFile="clover.xml"/>
</report>
</coverage>
To collect coverage, you can pick traditional XDebug or performant PCOV extension.
git diff master...HEAD > changes.patch
vendor/bin/coverage-guard check clover.xml --patch changes.patch
coverage-guard.php file in your project root to customize behavior and set up your CoverageRules.
vendor/bin/coverage-guard initShipMonk\CoverageGuard\Config<?php
use ShipMonk\CoverageGuard\Config;
use ShipMonk\CoverageGuard\Rule\EnforceCoverageForMethodsRule;
$config = new Config();
// Your rules what must be covered
$config->addRule(new EnforceCoverageForMethodsRule(
requiredCoveragePercentage: 50,
minMethodChangePercentage: 50, // when --patch is provided, check only methods changed by more than 50%
minExecutableLines: 5, // only check methods with at least 5 executable lines
));
// Replace prefix of absolute paths in coverage files
// Handy if you want to reuse clover.xml generated in CI
$config->addCoveragePathMapping('/absolute/ci/prefix', __DIR__);
// As filepaths in git patches are relative to the project root, you can specify the root directory here
// It gets autodetected if cwd is inside some git repository
$config->setGitRoot(__DIR__);
// Make CLI file paths clickable to your IDE
// Available placeholders: {file}, {relFile}, {line}
$config->setEditorUrl('phpstorm://open?file={file}&line={line}');
return $config;
CoverageRule and pass it to Config::addRule() method:
EnforceCoverageForMethodsRule or usages in the wild:
The CodeBlock class passed to CoverageRule is aware which line is executable, changed and covered.
Also, you can use reflection to pinpoint your rules.
This allows you to setup huge variety of rules, examples:
Controller methods must have at least 50% coverage#[NoCoverageAllowed] attribute is used--help show generic help (or command help when combined with command name)--no-color to disable colors (NO_COLOR env is also supported)--color to force colors even when output is not a TTYRun vendor/bin/coverage-guard <command> --help for command-specific options.
| Format | Filesize | Rating | Notes |
|---|---|---|---|
clover (.xml) |
(baseline) | 🟢 Best | Usable in PHPStorm coverage visualization. Allows better integrity checks. |
cobertura (.xml) |
1.7x bigger | 🟡 OK | Usable in GitLab coverage visualization |
php (.cov) |
8x - 40x bigger | 🔴 Avoid | May produce warnings on old PHPUnit when xdebug is not active. Good coverage causes HUGE filesizes easily reaching over 100 MB. |
checkvendor/bin/coverage-guard check clover.xml
Options:
--verbose – show detailed processing information--patch – path to git diff, to check coverage only for changed files & methods--config – path to custom PHP configmerge & convertclover, cobertura, php (autodetected)clover, coberturavendor/bin/coverage-guard merge coverage/*.xml > merged.xml
vendor/bin/coverage-guard convert cobertura.xml --output-format clover > clover.xml
Options:
--output-format – output format (clover or cobertura)--indent – output XML indentation (defaults to 4 spaces); for tabs use --indent=$'\t'--config – path to custom PHP configpatch-coveragecoverage: '/Coverage:\s+(\d+\.\d+%)/'
git diff master...HEAD > changes.patch
vendor/bin/coverage-guard patch-coverage clover.xml --patch changes.patch
Options:
--patch – path to diff file (required)--config – path to custom PHP configOutput example:
Patch Coverage Statistics:
Changed executable lines: 45
Covered lines: 38
Uncovered lines: 7
Coverage: 84.44%
initcoverage-guard.php configuration file in your current directory.
vendor/bin/coverage-guard init
phpunit/php-code-coverage for loading coverage cov filessebastian/diff for processing diff/patch filesext-libxml and ext-simplexml for loading coverage XML filesext-dom for check and merge commandsext-tokenizer to see syntax highlighted code blockscomposer checkcomposer fix:csHow can I help you explore Laravel packages today?