You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
AddDoesNotPerformAssertionToNonAssertingTestRector: misses assertions outside the test method body (parent::, expectUserDeprecationMessage(), lifecycle methods) #9965
AddDoesNotPerformAssertionToNonAssertingTestRector only looks at assertions reachable from the test method body. PHPUnit counts assertions from more places, so tests that do assert get #[DoesNotPerformAssertions] and then fail as risky.
#[DoesNotPerformAssertions] is added to ReproTest::testInherited(), ReproTest::testDeprecation() and LifecycleReproTest::testSomething(). With failOnRisky, all three then fail:
This test is not expected to perform assertions but performed 1 assertion
Expected Behavior
None of them is changed. Only tests that really perform no assertions should get the attribute.
Cause
expectUserDeprecationMessage() and expectUserDeprecationMessageMatches() are missing from AssertCallAnalyzer::ASSERT_METHOD_NAME_PREFIXES. PHPUnit counts every expected deprecation as an assertion (TestCase::verifyDeprecationExpectations() increments numberOfAssertionsPerformed per expectation).
parent::testInherited() is not followed into the parent method. AssertCallAnalyzer::resolveClassMethodFromCall() resolves a StaticCall through the type of $call->class, and for parent the type resolver returns a union of all ancestors instead of a single class type.
Assertions in lifecycle methods (setUp(), tearDown(), assertPreConditions(), assertPostConditions(), #[Before]/#[After]/#[PreCondition]/#[PostCondition] methods) are not considered, although PHPUnit counts them toward every test of the class.
We found this running the composer-based PHPUnit set on Drupal core (https://www.drupal.org/i/3638148), where 68 tests became risky. 17 use expectUserDeprecationMessage(), 22 only call parent::test*() (config entity validation tests), and most of the rest assert in base-class lifecycle methods. Running the rule over core's test directories gives 83 methods on rector-phpunit main and 3 with the PR above.
changed the title [-]AddDoesNotPerformAssertionToNonAssertingTestRector: misses parent::test*() calls and expectUserDeprecationMessage()[/-][+]AddDoesNotPerformAssertionToNonAssertingTestRector: misses assertions outside the test method body (parent::, expectUserDeprecationMessage(), lifecycle methods)[/+]on Nov 14, 2026
Activity
bbrala commentedon Nov 14, 2026
(fix also incoming ;))
fix: skip PHPUnit AddDoesNotPerformAssertionToNonAssertingTestRector …
[PHPUnit60] Skip tests in classes with asserting lifecycle methods in…
[-]AddDoesNotPerformAssertionToNonAssertingTestRector: misses parent::test*() calls and expectUserDeprecationMessage()[/-][+]AddDoesNotPerformAssertionToNonAssertingTestRector: misses assertions outside the test method body (parent::, expectUserDeprecationMessage(), lifecycle methods)[/+][PHPUnit60] Skip tests in classes with asserting lifecycle methods in…