Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions src/PendingCalls/TestCall.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
use PHPUnit\Framework\AssertionFailedError;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\CoversFunction;
use PHPUnit\Framework\Attributes\CoversNothing;
use PHPUnit\Framework\Attributes\CoversTrait;
use PHPUnit\Framework\Attributes\Group;
use PHPUnit\Framework\TestCase;
Expand Down Expand Up @@ -571,6 +572,16 @@ public function coversFunction(string ...$functions): self
return $this;
}

public function coversNothing(): self
{
$this->testCaseMethod->attributes[] = new Attribute(
CoversNothing::class,
[],
);

return $this;
}

/**
* @param array<class-string|string>|class-string ...$classes
*/
Expand Down
8 changes: 7 additions & 1 deletion tests/.snapshots/success.txt
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,12 @@
PASS Tests\Features\Covers\ClassCoverage
✓ it uses the correct PHPUnit attribute for class

PASS Tests\Features\Covers\CoversNothing
✓ it uses the correct PHPUnit attribute for covers nothing
✓ describe → it uses the correct PHPUnit attribute for covers nothing
✓ it is not risky when coverage metadata is required
✓ it does not conflict with covers in the same file

PASS Tests\Features\Covers\ExceptionHandling
✓ it throws exception if no class nor method has been found

Expand Down Expand Up @@ -2265,4 +2271,4 @@
✓ pass with dataset with ('my-datas-set-value')
✓ within describe → pass with dataset with ('my-datas-set-value')

Tests: 2 deprecated, 4 warnings, 5 incomplete, 2 notices, 40 todos, 35 skipped, 1606 passed (3505 assertions)
Tests: 2 deprecated, 4 warnings, 5 incomplete, 2 notices, 40 todos, 35 skipped, 1610 passed (3516 assertions)
54 changes: 54 additions & 0 deletions tests/Features/Covers/CoversNothing.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<?php

use PHPUnit\Framework\Attributes\CoversNothing;
use Symfony\Component\Process\Process;

$run = function (string ...$arguments): array {
$process = new Process(
['php', 'bin/pest', '--configuration', 'tests/Fixtures/Suites/CoversNothing.xml', ...$arguments],
dirname(__DIR__, 3),
['COLLISION_PRINTER' => 'DefaultPrinter', 'COLLISION_IGNORE_DURATION' => 'true', 'PAO_DISABLE' => '1'],
);

$process->run();

return [
'output' => removeAnsiEscapeSequences($process->getOutput().$process->getErrorOutput()),
'code' => $process->getExitCode(),
];
};

it('uses the correct PHPUnit attribute for covers nothing', function (): void {
$attributes = new ReflectionMethod($this, $this->name())->getAttributes();

expect($attributes[2]->getName())->toBe(CoversNothing::class)
->and($attributes[2]->getArguments())->toBeEmpty();
})->coversNothing();

describe('describe', function (): void {
it('uses the correct PHPUnit attribute for covers nothing', function (): void {
$attributes = new ReflectionMethod($this, $this->name())->getAttributes();

expect($attributes[2]->getName())->toBe(CoversNothing::class)
->and($attributes[2]->getArguments())->toBeEmpty();
});
})->coversNothing();

it('is not risky when coverage metadata is required', function () use ($run): void {
$result = $run();

expect($result['output'])
->toContain('✓ covers nothing')
->toContain('! declares no coverage metadata → This test does not define a code coverage target but is expected to do so')
->toContain('Tests: 1 risky, 1 passed (2 assertions)')
->and($result['code'])->toBe(1);
})->skipOnWindows();

it('does not conflict with covers in the same file', function () use ($run): void {
$result = $run('tests/Fixtures/Suites/CoversNothingWithCovers.php');

expect($result['output'])
->toContain('✓ covers nothing')
->toContain('Tests: 2 passed (2 assertions)')
->and($result['code'])->toBe(0);
})->skipOnWindows();
9 changes: 9 additions & 0 deletions tests/Fixtures/Suites/CoversNothing.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php

test('covers nothing', function (): void {
expect(true)->toBeTrue();
})->coversNothing();

test('declares no coverage metadata', function (): void {
expect(true)->toBeTrue();
});
15 changes: 15 additions & 0 deletions tests/Fixtures/Suites/CoversNothing.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.0/phpunit.xsd"
bootstrap="../../../vendor/autoload.php"
colors="true"
requireCoverageMetadata="true"
failOnRisky="true"
failOnWarning="true"
>
<testsuites>
<testsuite name="default">
<file>CoversNothing.php</file>
</testsuite>
</testsuites>
</phpunit>
13 changes: 13 additions & 0 deletions tests/Fixtures/Suites/CoversNothingWithCovers.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php

use Tests\Fixtures\Covers\CoversClass1;

covers(CoversClass1::class);

test('covers the class', function (): void {
expect(true)->toBeTrue();
});

test('covers nothing', function (): void {
expect(true)->toBeTrue();
})->coversNothing();
2 changes: 1 addition & 1 deletion tests/Visual/Parallel.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
$output = $run('--exclude-group=integration');
$output = implode("\n", array_slice(explode("\n", (string) $output), -10));

$expected = '2 deprecated, 4 warnings, 5 incomplete, 3 notices, 40 todos, 27 skipped, 1587 passed (3447 assertions)';
$expected = '2 deprecated, 4 warnings, 5 incomplete, 3 notices, 40 todos, 27 skipped, 1591 passed (3458 assertions)';

expect($output)
->toContain("Tests: {$expected}")
Expand Down
Loading