Skip to content

Commit b5fa1c2

Browse files
authored
feat: add support for covers attributes (#68)
1 parent fc78501 commit b5fa1c2

13 files changed

+71
-19
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,8 @@ Consider src namespace `Ns` and test namespace `Ns/Tests` then for test `Ns/Test
148148
You can use `@covers` or `@coversDefaultClass` annotations to link test with tested class.
149149
Use `@coversNothing` annotation to skip this check.
150150

151+
`#[CoversNothing]` and `#[CoversClass]` attributes are supported.
152+
151153
Don't forget to enable `"forceCoversAnnotation="true"` in phpunit config file.
152154

153155
```php

phpstan-baseline.neon

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
parameters:
2+
ignoreErrors:
3+
-
4+
message: "#^Parameter \\#1 \\$className of attribute class PHPUnit\\\\Framework\\\\Attributes\\\\CoversClass constructor expects class\\-string, string given\\.$#"
5+
count: 2
6+
path: tests/TestCheck/Fixtures/EveryTestHasSameNamespaceAsCoveredClass/tests/IgnoreMultipleCoversTest.php

phpstan.neon.dist

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,6 @@ parameters:
55
- %currentWorkingDirectory%/tests
66
ignoreErrors:
77
- "~Call to static method PHPUnit\\\\Framework\\\\Assert::assertTrue\\(\\) with true will always evaluate to true~"
8+
9+
includes:
10+
- phpstan-baseline.neon

src/TestCheck/EveryTestHasGroup.php

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
namespace Cdn77\TestUtils\TestCheck;
66

77
use Cdn77\EntityFqnExtractor\ClassExtractor;
8+
use PHPUnit\Framework\Attributes\Group;
89
use PHPUnit\Framework\TestCase;
910
use ReflectionClass;
1011

@@ -25,6 +26,26 @@ public function run(TestCase $testCaseContext): void
2526
{
2627
foreach ($this->filePathNames as $filePathName) {
2728
$classReflection = new ReflectionClass(ClassExtractor::get($filePathName));
29+
if ($classReflection->isAbstract()) {
30+
continue;
31+
}
32+
33+
$groupAttributes = $classReflection->getAttributes(Group::class);
34+
foreach ($groupAttributes as $groupAttribute) {
35+
$testCaseContext::assertContains(
36+
$groupAttribute->getArguments()[0],
37+
$this->allowedGroups,
38+
sprintf(
39+
'Test "%s" has invalid @group annotation "%s"',
40+
$classReflection->getName(),
41+
$groupAttribute->getArguments()[0],
42+
),
43+
);
44+
}
45+
46+
if ($groupAttributes !== []) {
47+
continue;
48+
}
2849

2950
$this->validateDocComment($testCaseContext, $classReflection);
3051
}

src/TestCheck/EveryTestHasSameNamespaceAsCoveredClass.php

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
namespace Cdn77\TestUtils\TestCheck;
66

77
use Cdn77\EntityFqnExtractor\ClassExtractor;
8+
use PHPUnit\Framework\Attributes\CoversClass;
9+
use PHPUnit\Framework\Attributes\CoversNothing;
810
use PHPUnit\Framework\TestCase;
911
use ReflectionClass;
1012

@@ -38,22 +40,27 @@ public function run(TestCase $testCaseContext): void
3840
foreach ($this->filePathNames as $file) {
3941
$classReflection = new ReflectionClass(ClassExtractor::get($file));
4042

43+
$attributesCoversClass = $classReflection->getAttributes(CoversClass::class);
44+
$attributesCoversNothing = $classReflection->getAttributes(CoversNothing::class);
45+
4146
$docComment = $classReflection->getDocComment();
4247
if ($docComment === false) {
4348
$docComment = '';
4449
}
4550

46-
$matchesCovers = preg_match_all(self::PatternCovers, $docComment, $coversMatches) > 0;
47-
$matchesCoversNothing = preg_match(self::PatternCoversNothing, $docComment) === 1;
51+
$hasCovers = preg_match_all(self::PatternCovers, $docComment, $coversMatches) > 0
52+
|| $attributesCoversClass !== [];
53+
$hasCoversNothing = preg_match(self::PatternCoversNothing, $docComment) === 1
54+
|| $attributesCoversNothing !== [];
4855

49-
if ($matchesCovers && $matchesCoversNothing) {
56+
if ($hasCovers && $hasCoversNothing) {
5057
$testCaseContext::fail(sprintf(
51-
'Test file "%s" contains both @covers and @coversNothing annotations.',
58+
'Specifying CoversClass and CoversNothing attributes at the same time makes no sense (in "%s").',
5259
$file,
5360
));
5461
}
5562

56-
if ($matchesCoversNothing || $matchesCovers) {
63+
if ($hasCoversNothing || $hasCovers) {
5764
continue;
5865
}
5966

tests/TestCheck/EveryTestHasSameNamespaceAsCoveredClassTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ public static function providerFail(): Generator
5656
{
5757
yield [
5858
'CoversAndCoversNothingTest.php',
59-
'contains both @covers and @coversNothing annotations',
59+
'Specifying CoversClass and CoversNothing attributes at the same time',
6060
];
6161

6262
yield [

tests/TestCheck/Fixtures/EveryTestHasSameNamespaceAsCoveredClass/tests/CoveredClassWithSomeWhitespaceTest.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@
44

55
namespace Cdn77\TestUtils\Tests\Tests\TestCheck\Fixtures\EveryTestHasSameNamespaceAsCoveredClass;
66

7-
/** @covers \Cdn77\TestUtils\Tests\TestCheck\Fixtures\EveryTestHasSameNamespaceAsCoveredClass\SameNamespace */
7+
use Cdn77\TestUtils\Tests\TestCheck\Fixtures\EveryTestHasSameNamespaceAsCoveredClass\SameNamespace;
8+
use PHPUnit\Framework\Attributes\CoversClass;
9+
10+
#[CoversClass(SameNamespace::class)]
811
final class CoveredClassWithSomeWhitespaceTest
912
{
1013
}

tests/TestCheck/Fixtures/EveryTestHasSameNamespaceAsCoveredClass/tests/CoversAndCoversNothingTest.php

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,12 @@
44

55
namespace Cdn77\TestUtils\Tests\Tests\TestCheck\Fixtures\EveryTestHasSameNamespaceAsCoveredClass;
66

7-
/**
8-
* @coversNothing
9-
* @covers \stdClass
10-
*/
7+
use PHPUnit\Framework\Attributes\CoversClass;
8+
use PHPUnit\Framework\Attributes\CoversNothing;
9+
use stdClass;
10+
11+
#[CoversClass(stdClass::class)]
12+
#[CoversNothing()]
1113
final class CoversAndCoversNothingTest
1214
{
1315
}

tests/TestCheck/Fixtures/EveryTestHasSameNamespaceAsCoveredClass/tests/CoversNothingTest.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@
44

55
namespace Cdn77\TestUtils\Tests\Tests\TestCheck\Fixtures\EveryTestHasSameNamespaceAsCoveredClass;
66

7-
/** @coversNothing */
7+
use PHPUnit\Framework\Attributes\CoversNothing;
8+
9+
#[CoversNothing]
810
final class CoversNothingTest
911
{
1012
}

tests/TestCheck/Fixtures/EveryTestHasSameNamespaceAsCoveredClass/tests/IgnoreMultipleCoversTest.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@
44

55
namespace Cdn77\TestUtils\Tests\Tests\TestCheck\Fixtures\EveryTestHasSameNamespaceAsCoveredClass;
66

7-
/**
8-
* @covers Cdn77\TestUtils\Tests\TestCheck\Fixtures\EveryTestHasSameNamespaceAsTestedClass\A
9-
* @covers Cdn77\TestUtils\Tests\TestCheck\Fixtures\EveryTestHasSameNamespaceAsTestedClass\B
10-
*/
7+
use PHPUnit\Framework\Attributes\CoversClass;
8+
9+
#[CoversClass('\Cdn77\TestUtils\Tests\TestCheck\Fixtures\EveryTestHasSameNamespaceAsTestedClass\A')]
10+
#[CoversClass('\Cdn77\TestUtils\Tests\TestCheck\Fixtures\EveryTestHasSameNamespaceAsTestedClass\B')]
1111
final class IgnoreMultipleCoversTest
1212
{
1313
}

tests/TestCheck/Fixtures/EveryTestHasSameNamespaceAsCoveredClass/tests/SameNamespaceAsLinkedCoveredClassTest.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@
44

55
namespace Cdn77\TestUtils\Tests\Tests\TestCheck\Fixtures\EveryTestHasSameNamespaceAsCoveredClass;
66

7-
/** @covers Cdn77\TestUtils\Tests\TestCheck\Fixtures\EveryTestHasSameNamespaceAsCoveredClass\SameNamespace */
7+
use PHPUnit\Framework\Attributes\CoversClass;
8+
9+
#[CoversClass('\Cdn77\TestUtils\Tests\TestCheck\Fixtures\EveryTestHasSameNamespaceAsCoveredClass\SameNamespace')]
810
final class SameNamespaceAsLinkedCoveredClassTest
911
{
1012
}

tests/TestCheck/Fixtures/WithGroup.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@
44

55
namespace Cdn77\TestUtils\Tests\TestCheck\Fixtures;
66

7-
/** @group unit */
7+
use PHPUnit\Framework\Attributes\Group;
8+
9+
#[Group('unit')]
810
final class WithGroup
911
{
1012
}

tests/TestCheck/Fixtures/WithUnlistedGroup.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@
44

55
namespace Cdn77\TestUtils\Tests\TestCheck\Fixtures;
66

7-
/** @group Eheu, raptus advena! */
7+
use PHPUnit\Framework\Attributes\Group;
8+
9+
#[Group('Eheu, raptus advena!')]
810
final class WithUnlistedGroup
911
{
1012
}

0 commit comments

Comments
 (0)