Repository navigation
[PHPUnit60] Skip tests in classes with asserting lifecycle methods in AddDoesNotPerformAssertionToNonAssertingTestRector - #827
Open
bbrala wants to merge 1 commit into
Conversation
… AddDoesNotPerformAssertionToNonAssertingTestRector (rectorphp/rector#9965)
TomasVotruba
force-pushed
the
does-not-perform-assertions-lifecycle
branch
from
November 14, 2026 17:14
e6105ff to
d17bdaf
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Part of rectorphp/rector#9965, split from #822. Stacked on #826: only the last commit (e6105ff) is new here.
PHPUnit counts assertions made in lifecycle methods towards the test. A test whose own body asserts nothing still "performs assertions" when
setUp(),tearDown(),assertPreConditions(),assertPostConditions(), a#[Before]/#[After]/#[PreCondition]/#[PostCondition]method or a@before/@aftermethod asserts, in the class, an ancestor or a used trait.AddDoesNotPerformAssertionToNonAssertingTestRectoradds#[DoesNotPerformAssertions]to those tests, and withfailOnRiskythey then fail.Change
New
LifecycleMethodAssertAnalyzer. A test is skipped when its class, an ancestor or a used trait has an asserting lifecycle method.getFile()->getNewStmts()), so the file being processed is not parsed again. The rule stays onClassMethod.AstResolver, but only when a cheap regex on the file contents finds a hook name or aBefore/After/PreCondition/PostConditionattribute or annotation. The regex can give false positives (an extra parse), never miss a hook.parent::<hook>(). Each hook is evaluated on its own, so longparent::setUp()chains are not cut off byAssertCallAnalyzer's nesting limit.$thisis unknown.$this->x(),self::x()andstatic::x()are resolved against the trait's own methods; if that fails (a method of the using class), the call is treated as possibly asserting.Two behaviour changes worth a look:
TestCase) now counts as possibly asserting, so such tests keep missing the attribute. This only ever removes a change, never adds a wrong one.Bench
The #824 bench now has 3 scenarios: the original inherited-test shape, every test class with its own
setUp(), and asserting hooks at the top of each parent chain. It builds aFileper test class and sets it onCurrentFileProvider, likeAbstractRectorTestCasedoes, because the rule now reads the current file. CPU, 3 runs, local ddev PHP 8.5:mainsetUp()On
mainand #826 the "asserting hooks" scenario changes all 1800 methods; with this PR none. The remaining cost is parsing the ~30 parent files that declare hooks.Tests
New fixtures cover: own and inherited
setUp()/tearDown()/assertPostConditions(),#[Before](also aliased),@after, a 7-levelparent::setUp()chain, hooks and helpers in traits (same file, other file, used by a parent),parent::setUp()in a trait hook, overrides without a parent call, anonymous classes, and abstract classes. Full suite (727 tests), ECS, Rector, class-leak and finalize-classes pass. PHPStan: the same 6 pre-existing errors asmain.Context
Found running the composer-based PHPUnit set on Drupal core (https://www.drupal.org/i/3638148), which runs with
failOnRiskyand has many base classes asserting insetUp()orassertPostConditions().