From a899ac4d60cdbc27eb3200c36005aa54f2ae97f3 Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Sun, 9 Aug 2026 18:43:17 +0200 Subject: [PATCH] [PHPUnit60] Add DoesNotPerformAssertions attribute directly and skip traits in AddDoesNotPerformAssertionToNonAssertingTestRector --- .../Fixture/fixture.php.inc | 4 +- .../remove_add_to_assertion_count.php.inc | 4 +- ...dd_to_assertion_count_in_try_catch.php.inc | 4 +- ...dd_to_assertion_count_with_comment.php.inc | 4 +- .../Fixture/skip_trait.php.inc | 11 ++++++ .../Fixture/test_in_annotation.php.inc | 2 +- ..._in_annotation_with_test_attribute.php.inc | 4 +- ...rformAssertionToNonAssertingTestRector.php | 38 ++++++++++++++++--- src/Enum/PHPUnitAttribute.php | 2 + .../Fixture/some_test.php.inc | 2 +- 10 files changed, 53 insertions(+), 22 deletions(-) create mode 100644 rules-tests/PHPUnit60/Rector/ClassMethod/AddDoesNotPerformAssertionToNonAssertingTestRector/Fixture/skip_trait.php.inc diff --git a/rules-tests/PHPUnit60/Rector/ClassMethod/AddDoesNotPerformAssertionToNonAssertingTestRector/Fixture/fixture.php.inc b/rules-tests/PHPUnit60/Rector/ClassMethod/AddDoesNotPerformAssertionToNonAssertingTestRector/Fixture/fixture.php.inc index 60476f34..9dfeb05c 100644 --- a/rules-tests/PHPUnit60/Rector/ClassMethod/AddDoesNotPerformAssertionToNonAssertingTestRector/Fixture/fixture.php.inc +++ b/rules-tests/PHPUnit60/Rector/ClassMethod/AddDoesNotPerformAssertionToNonAssertingTestRector/Fixture/fixture.php.inc @@ -18,9 +18,7 @@ namespace Rector\PHPUnit\Tests\PHPUnit60\Rector\ClassMethod\AddDoesNotPerformAss class SomeClass extends \PHPUnit\Framework\TestCase { - /** - * @doesNotPerformAssertions - */ + #[\PHPUnit\Framework\Attributes\DoesNotPerformAssertions] public function test() { $nothing = 5; diff --git a/rules-tests/PHPUnit60/Rector/ClassMethod/AddDoesNotPerformAssertionToNonAssertingTestRector/Fixture/remove_add_to_assertion_count.php.inc b/rules-tests/PHPUnit60/Rector/ClassMethod/AddDoesNotPerformAssertionToNonAssertingTestRector/Fixture/remove_add_to_assertion_count.php.inc index f9b21df4..4b2dc5dc 100644 --- a/rules-tests/PHPUnit60/Rector/ClassMethod/AddDoesNotPerformAssertionToNonAssertingTestRector/Fixture/remove_add_to_assertion_count.php.inc +++ b/rules-tests/PHPUnit60/Rector/ClassMethod/AddDoesNotPerformAssertionToNonAssertingTestRector/Fixture/remove_add_to_assertion_count.php.inc @@ -23,9 +23,7 @@ namespace Rector\PHPUnit\Tests\PHPUnit60\Rector\ClassMethod\AddDoesNotPerformAss class RemoveAddToAssertionCount extends \PHPUnit\Framework\TestCase { - /** - * @doesNotPerformAssertions - */ + #[\PHPUnit\Framework\Attributes\DoesNotPerformAssertions] public function test() { $this->someMethodCall(); diff --git a/rules-tests/PHPUnit60/Rector/ClassMethod/AddDoesNotPerformAssertionToNonAssertingTestRector/Fixture/remove_add_to_assertion_count_in_try_catch.php.inc b/rules-tests/PHPUnit60/Rector/ClassMethod/AddDoesNotPerformAssertionToNonAssertingTestRector/Fixture/remove_add_to_assertion_count_in_try_catch.php.inc index bbd5decd..a99a201a 100644 --- a/rules-tests/PHPUnit60/Rector/ClassMethod/AddDoesNotPerformAssertionToNonAssertingTestRector/Fixture/remove_add_to_assertion_count_in_try_catch.php.inc +++ b/rules-tests/PHPUnit60/Rector/ClassMethod/AddDoesNotPerformAssertionToNonAssertingTestRector/Fixture/remove_add_to_assertion_count_in_try_catch.php.inc @@ -26,9 +26,7 @@ namespace Rector\PHPUnit\Tests\PHPUnit60\Rector\ClassMethod\AddDoesNotPerformAss class RemoveAddToAssertionCountInTryCatch extends \PHPUnit\Framework\TestCase { - /** - * @doesNotPerformAssertions - */ + #[\PHPUnit\Framework\Attributes\DoesNotPerformAssertions] public function test() { try { diff --git a/rules-tests/PHPUnit60/Rector/ClassMethod/AddDoesNotPerformAssertionToNonAssertingTestRector/Fixture/remove_add_to_assertion_count_with_comment.php.inc b/rules-tests/PHPUnit60/Rector/ClassMethod/AddDoesNotPerformAssertionToNonAssertingTestRector/Fixture/remove_add_to_assertion_count_with_comment.php.inc index 28f60efa..e137dfff 100644 --- a/rules-tests/PHPUnit60/Rector/ClassMethod/AddDoesNotPerformAssertionToNonAssertingTestRector/Fixture/remove_add_to_assertion_count_with_comment.php.inc +++ b/rules-tests/PHPUnit60/Rector/ClassMethod/AddDoesNotPerformAssertionToNonAssertingTestRector/Fixture/remove_add_to_assertion_count_with_comment.php.inc @@ -24,9 +24,7 @@ namespace Rector\PHPUnit\Tests\PHPUnit60\Rector\ClassMethod\AddDoesNotPerformAss class RemoveAddToAssertionCountWithComment extends \PHPUnit\Framework\TestCase { - /** - * @doesNotPerformAssertions - */ + #[\PHPUnit\Framework\Attributes\DoesNotPerformAssertions] public function test() { $this->someMethodCall(); diff --git a/rules-tests/PHPUnit60/Rector/ClassMethod/AddDoesNotPerformAssertionToNonAssertingTestRector/Fixture/skip_trait.php.inc b/rules-tests/PHPUnit60/Rector/ClassMethod/AddDoesNotPerformAssertionToNonAssertingTestRector/Fixture/skip_trait.php.inc new file mode 100644 index 00000000..93b70de0 --- /dev/null +++ b/rules-tests/PHPUnit60/Rector/ClassMethod/AddDoesNotPerformAssertionToNonAssertingTestRector/Fixture/skip_trait.php.inc @@ -0,0 +1,11 @@ +removeAddToAssertionCountCalls($node); + // the attribute is available since PHPUnit 10, prefer it over the annotation + if ($this->reflectionProvider->hasClass(PHPUnitAttribute::DOES_NOT_PERFORM_ASSERTIONS)) { + $node->attrGroups[] = new AttributeGroup([ + new Attribute(new FullyQualified(PHPUnitAttribute::DOES_NOT_PERFORM_ASSERTIONS)), + ]); + + return $node; + } + $phpDocInfo = $this->phpDocInfoFactory->createFromNodeOrEmpty($node); $phpDocInfo->addPhpDocTagNode(new PhpDocTagNode('@doesNotPerformAssertions', new GenericTagValueNode(''))); @@ -132,6 +145,11 @@ private function shouldSkipClassMethod(ClassMethod $classMethod): bool return true; } + // we have no idea how the trait is used, the using class can assert on its own + if ($this->isInTrait($classMethod)) { + return true; + } + // the parent test case asserts in its own integration methods if ($this->isInTwigIntegrationTestCase($classMethod)) { return true; @@ -192,6 +210,16 @@ private function isAddToAssertionCountExpression(Node $node): bool return $this->isName($methodCall->name, 'addToAssertionCount'); } + private function isInTrait(ClassMethod $classMethod): bool + { + $classReflection = $this->reflectionResolver->resolveClassReflection($classMethod); + if (! $classReflection instanceof ClassReflection) { + return false; + } + + return $classReflection->isTrait(); + } + private function isInTwigIntegrationTestCase(ClassMethod $classMethod): bool { $classReflection = $this->reflectionResolver->resolveClassReflection($classMethod); @@ -212,7 +240,7 @@ private function hasAssertingAnnotationOrAttribute(ClassMethod $classMethod): bo return $this->phpAttributeAnalyzer->hasPhpAttribute( $classMethod, - 'PHPUnit\Framework\Attributes\DoesNotPerformAssertions' + PHPUnitAttribute::DOES_NOT_PERFORM_ASSERTIONS ); } } diff --git a/src/Enum/PHPUnitAttribute.php b/src/Enum/PHPUnitAttribute.php index 9517d29c..cca04295 100644 --- a/src/Enum/PHPUnitAttribute.php +++ b/src/Enum/PHPUnitAttribute.php @@ -24,6 +24,8 @@ final class PHPUnitAttribute public const string TEST = 'PHPUnit\Framework\Attributes\Test'; + public const string DOES_NOT_PERFORM_ASSERTIONS = 'PHPUnit\Framework\Attributes\DoesNotPerformAssertions'; + /** * Since PHPUnit 12.5.2 * @see https://github.com/sebastianbergmann/phpunit/commit/24c208d6a340c3071f28a9b5cce02b9377adfd43 diff --git a/tests/Issues/PHPUnit10DataProvider/Fixture/some_test.php.inc b/tests/Issues/PHPUnit10DataProvider/Fixture/some_test.php.inc index 8d2b47cd..3441ffb7 100644 --- a/tests/Issues/PHPUnit10DataProvider/Fixture/some_test.php.inc +++ b/tests/Issues/PHPUnit10DataProvider/Fixture/some_test.php.inc @@ -27,8 +27,8 @@ namespace Rector\PHPUnit\Tests\Issues\PHPUnit10DataProvider\Fixture; final class SomeTest extends \PHPUnit\Framework\TestCase { #[\PHPUnit\Framework\Attributes\DataProvider('fooProvider')] - #[\PHPUnit\Framework\Attributes\Test] #[\PHPUnit\Framework\Attributes\DoesNotPerformAssertions] + #[\PHPUnit\Framework\Attributes\Test] public function it_should_do_stuff(string $foo): void { }