Download the PHP package savage-days/phpunit-case-coverage without Composer
On this page you can find all versions of the php package savage-days/phpunit-case-coverage. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.
Download savage-days/phpunit-case-coverage
More information about savage-days/phpunit-case-coverage
Files in savage-days/phpunit-case-coverage
Package phpunit-case-coverage
Short Description Opt-in behavioral case coverage for PHPUnit doubles.
License MIT
Informations about the package phpunit-case-coverage
PHPUnit Case Coverage
PHPUnit Case Coverage is an opt-in extension that makes meaningful, developer-declared outcomes of a dependency visible in consumer tests.
PHPUnit remains responsible for correctness: assertions and mock expectations still prove the behaviour of the system under test. Case Coverage answers a complementary question: which declared dependency outcomes has this consumer scope exercised?
It is deliberately test-layer only. Production classes do not receive attributes, interfaces, or other metadata from this package.
Requirements
- PHP 8.2+
- PHPUnit 9.6, 10.5, or 11
Installation
Install from a published repository:
Register the extension in the consuming project's phpunit.xml:
For PHPUnit 9.6, use its legacy listener configuration instead; the event extension API used by PHPUnit 10/11 does not exist in PHPUnit 9:
Define cases
A CaseSet is a test-side catalogue for one target class or interface. Every public static method returning CaseDefinition declares exactly one outcome for exactly one target method.
Supported outcomes are deliberately small:
completes() is valid only for a target method declared with void. Case definitions are validated when the catalogue is used: the target type and target method must exist.
Apply one case
Use case() in an ordinary PHPUnit test. A case becomes covered only when apply() runs; merely creating a case does not affect the report.
apply() checks that the PHPUnit double implements or extends the CaseSet target, configures the declared return/throw outcome, and records coverage. It does not configure call counts, arguments, or expectations; keep those as normal PHPUnit mock setup:
Run a group without a provider method in the test class
Groups collect semantically equivalent cases. Declare membership with #[Group], then expose one public static provider method on the CaseSet. PHPUnit's DataProviderExternal keeps the test method focused on the test itself:
PHPUnit invokes PaymentClientCases::temporaryFailures(), which delegates to forGroup('temporaryFailures'). The resulting datasets are named after their cases, for example timeout and connectionError.
When a new case is added to temporaryFailures, this test automatically gains a new PHPUnit dataset. DataProviderExternal requires a real public static method, so that small provider method is necessary; it belongs beside the group, not in every test class.
For a one-case data provider, use CaseSet::forCase('approved'). Most one-case tests are simpler with CaseSet::case('approved')->apply($double).
PHPUnit 9.6 does not support DataProviderExternal attributes. It supports the same external static provider with its legacy annotation:
Coverage semantics
Coverage is aggregated by PHPUnit test class. It begins only when apply() is called.
Once any case for a target method is applied, all declared cases of that same target method become the denominator for that test class. Cases for other methods in the same CaseSet are not shown unless one of their cases is applied.
For example, if a UserCases catalogue declares four outcomes for User::getIdentity() and a UserTest applies only exception and id, the report is:
This is behavioural coverage of the declared space, not proof that the catalogue contains every possible real-world outcome.
Run the report
Normal PHPUnit execution is unchanged and produces no Case Coverage output:
Use the package wrapper and --case-coverage to request the report:
All other arguments are forwarded to PHPUnit:
The wrapper is necessary because PHPUnit parses command-line options before extensions load; an integration cannot directly add a new native vendor/bin/phpunit option. It enables the PHPUnit 9 listener and PHPUnit 10/11 extension alike.
What the package does not do
- It does not infer cases from test names or ordinary mock configuration.
- It does not modify generated PHPUnit doubles or replace PHPUnit mock APIs.
- It does not generate combinations across different dependency methods.
- It does not add production-code metadata or validate external provider behaviour.
- It does not enforce coverage thresholds in CI.
The package stays intentionally small: cases declare what a dependency produces; PHPUnit tests declare how the consumer uses it.