Skip to content

feat: restore coversNothing() - #1981

Merged
nunomaduro merged 1 commit into
pestphp:5.xfrom
gsmeira:restore-covers-nothing
Oct 18, 2026
Merged

nunomaduro merged 1 commit into
pestphp:5.xfrom
gsmeira:restore-covers-nothing

Conversation

@gsmeira

@gsmeira gsmeira commented Oct 18, 2026

Copy link
Copy Markdown
Contributor

What:

  • Bug Fix
  • New Feature

Description:

This PR restores ->coversNothing(). It adds PHPUnit's #[CoversNothing] attribute to the method of one test, the same way Pest 3 did:

covers(Invoice::class);

it('calculates the total', function () {
    // ...
});

it('boots the container', function () {
    // ...
})->coversNothing();

arch('app')->expect('App')->not->toUse(['dd', 'dump'])->coversNothing();

describe('smoke', function () {
    // ...
})->coversNothing();

With requireCoverageMetadata="true", PHPUnit flags each test without coverage metadata as risky. Today a Pest test can only satisfy that setting with covers(), so tests that cover no code have no public way to say so. Typical examples are arch() tests and smoke tests. The only workaround reaches into @internal API ($call->testCaseMethod->attributes[] = new Attribute(CoversNothing::class, [])).

Why it was removed. PHPUnit 12.3.0 deprecated #[CoversNothing] on test methods (sebastianbergmann/phpunit#6246, ChangeLog-12.3). Pest 4 then dropped ->coversNothing() in 711a60c (4.0.0-beta.1, first tagged in v4.0.0). The 3.x line still has it (v3.8.7).

Why it is safe now. PHPUnit 13.3.0 (2026-08-07) allows #[CoversNothing] on methods again (sebastianbergmann/phpunit#6722, 3ae334f, listed under "Added" in ChangeLog-13.3). On 13.4.3, the method-level attribute:

  • parses to Metadata::coversNothingOnMethod() with no deprecation.
  • counts as coverage metadata for requireCoverageMetadata (TestRunner::hasCoverageMetadata()).
  • turns off coverage collection for that test only (CodeCoverage::shouldCodeCoverageBeCollectedFor()).

PHPUnit warns only when a class-level #[CoversNothing] sits next to class-level #[Covers*] or #[Uses*] (CodeCoverage::coversNothingContradictsCoversOrUses() reads class-level metadata only). Pest writes covers() as class attributes and coversNothing() as a method attribute, so one file can use both without that warning.

composer.json requires phpunit/phpunit: ^13.4.3 and conflicts with >13.4.3. Thus each PHPUnit version that Pest 5.x installs accepts the method-level attribute.

Tests. tests/Features/Covers/CoversNothing.php follows the other tests/Features/Covers/* files:

  • ->coversNothing() puts CoversNothing on the test method, directly and through describe()->coversNothing().
  • A run of tests/Fixtures/Suites/CoversNothing.xml (requireCoverageMetadata="true", failOnRisky="true", failOnWarning="true") passes the coversNothing() test. It reports only the test without metadata as risky: 1 risky, 1 passed.
  • A file that uses covers(CoversClass1::class) and one ->coversNothing() test passes with no PHPUnit warning.

All four tests fail on 5.x with Call to undefined method PHPUnit\Framework\TestCase::coversNothing(). The last test also fails if the attribute goes on the class instead of the method, because PHPUnit then emits the #[Covers*] and #[Uses*] attributes do not have an effect when the #[CoversNothing] attribute is used warning. tests/.snapshots/success.txt and the summary in tests/Visual/Parallel.php are updated for the four new tests.

Related:

@nunomaduro
nunomaduro merged commit 1b3ca5b into pestphp:5.x Oct 18, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants