pestphp/pest-plugin-coverage
Official Pest plugin for code coverage: generate coverage reports from your Pest test suite, enforce minimum coverage thresholds, and integrate with PHPUnit coverage tooling through simple Pest commands and configuration.
Architecture fit. Coverage is a build-time and CI concern, not a runtime one. This plugin lives in require-dev, wraps PHPUnit's coverage engine (Xdebug or PCOV) behind Pest's CLI, and introduces no production surface, no service dependency, and no data path. Blast radius on removal is effectively zero — which is the good news. The bad news is that a zero-blast-radius dependency is also a zero-value dependency when the same capability ships natively with the framework. From a TPM's chair, the architectural question is not "does it fit" but "what does it buy us that the framework doesn't already give away for free." Today: nothing.
Integration feasibility. Trivially feasible in the narrow technical sense — one Composer add, Pest autodiscovery, no service provider, configuration via CLI flags plus phpunit.xml. Feasibility was never the constraint. The constraint is legitimacy: the repo is archived, has 9 stars, 0 dependents, a composite score of 0.0825, and an opportunity score of 22.31. For a component whose job is to gate releases, that is not a foundation — it is an unowned risk with a known expiry date.
Technical risk.
--coverage, --min, --coverage-clover, --coverage-html, and parallel-aware coverage natively. On any current major, this plugin is dead weight that can actively conflict with core flags.composer audit and dependency-review tooling will flag it abandoned, generating recurring review cycles for a package nobody wants to own.Key questions.
composer.lock? This alone may close the ticket.composer why pestphp/pest-plugin-coverage show deliberate intent or scaffold residue?--min flag in CI?pest --coverage --coverage-clover produce byte-comparable Clover/HTML output for the same commit?Stack fit. Composer-managed Laravel with Pest already in require-dev. Fit is nominal and only holds against older Pest/PHPUnit constraint sets. Confirm the environment before spending further effort:
composer show pestphp/pest
composer why pestphp/pest-plugin-coverage
On Pest 2.x/3.x the correct integration is no integration — use the runner's built-in flag directly.
Migration path. The exit is short and low-risk; schedule it as cleanup, not as a project.
phpunit.xml <source>/<coverage> blocks, README references.--min threshold as the last known-good reference.vendor/bin/pest --coverage --coverage-clover build/coverage.xml --min=<current threshold>.Compatibility. Verify three things explicitly: the plugin's pestphp/pest constraint against the resolved version, its phpunit/phpunit constraint against the resolved version, and that a coverage driver is present in CI (PCOV preferred; XDEBUG_MODE=coverage otherwise — Xdebug 3 does not run coverage in develop mode). A mismatch is a blocker with no upstream to escalate to, which is itself the argument for removal.
Sequencing. Do not schedule this as a standalone initiative. Bundle it into the next Pest/PHPUnit upgrade: upgrade → confirm native --coverage parity → remove plugin → update CI → document the replacement command. If the team is genuinely pinned to Pest v1, the plugin stays as an explicitly-labeled temporary liability with a named owner and a dated removal ticket — never as accepted permanent state.
Where the TPM actually creates leverage. The package was never the deliverable; the policy it was meant to enable is. Once native parity is confirmed, the TPM owns three decisions that outlast any dependency:
Maintenance. Zero upstream maintenance exists; 100% of any future fix transfers to us as an internal fork. For a dev-only tool that cost is tolerable in isolation, but for a CI gate it is unbudgeted engineering work with no vendor backstop and no roadmap.
Support. No maintainers, no triage queue, no security disclosure path. Internal engineers become de facto maintainers the moment something breaks. Record that explicitly in the dependency notes so no one assumes upstream cover exists when an incident lands at 2am.
Scaling. The plugin is not the bottleneck — coverage instrumentation is. As the suite grows, coverage becomes the slowest and most memory-hungry CI stage. Mitigations are engine-level and completely independent of plugin choice: PCOV over Xdebug, Pest parallel testing, testsuite/path filtering to keep coverage scoped to what matters, and running coverage on a single shard rather than every matrix leg. Because the wrapper is frozen, specifically validate that reports are complete rather than truncated under --parallel.
Failure modes to watch.
Ramp-up. Effectively zero for engineers — the CLI mirrors PHPUnit's, and the flags are documented by the framework the team already uses. The genuine ramp-up cost is organizational: making sure the team knows the dependency is frozen, who owns removal, and what command replaces it. That is one README line and one dated ticket, not a training plan.
TPM recommendation. Do not adopt. If already present, convert it immediately into technical debt with a dated removal ticket resolved via native Pest coverage on the next upgrade cycle. Archived status, 9 stars, 0 dependents, and an opportunity score of 22.31 all converge on the same conclusion: this package has been superseded by its own ecosystem. The correct integration is no integration. Spend the political capital on coverage policy — thresholds, ratchets, and pre-migration baselines — where the return is measured in defect confidence rather than dependency count.
How can I help you explore Laravel packages today?