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
ShouldCallParentMethodsRule is auto-fixable - #356
when adding a new setUp or tearDown method into a test-case base class, you get easily a lot of phpstan-phpunit errors in test-cases like:
Missing call to parent::setUp() method.
my idea is to add a parent::setUp() calls as a first statement into the existing setup method, and in tearDown I think we should append parent::tearDown to the very end of the existing tearDown.
The reason will be displayed to describe this comment to others. Learn more.
🟡 Changes recommended
The fixer appends an unreachable parent::tearDown() call after a throw, suppressing subsequent diagnostics without ensuring the parent method executes.
A tearDown() ending in exit/die or a known non-returning call such as self::fail() is marked fixable, but the appended parent::tearDown() is unreachable and suppresses the missing-parent diagnostic without running cleanup. The filter only recognizes returns and throws, although extension.neon:7–11 already registers fail, markTestSkipped, and markTestIncomplete as early-terminating. Withhold fixes for Node\Expr\Exit_ and recognized non-returning calls, and add corresponding fix fixtures.
The reason will be displayed to describe this comment to others. Learn more.
I ran the fixer on some cases that the fixture does not have.
One gap, the same kind as the throw case: a tearDown() that ends in a call that never returns still gets the call appended. For example:
protectedfunctiontearDown(): void
{
$this->fail('always');
parent::tearDown(); // added by the fix
}
exit(1); at the end gives the same result. After the fix the rule finds the call and reports nothing, but parent::tearDown() never runs. exit is an Expr\Exit_ node, so it could join the throw check. A call like $this->fail() needs its never return type. MethodReturnStatementsNode has getStatementResult(), which might be an option, but I did not try it.
These are correct:
A try/finally without a return gets the call after the finally block.
fn () => throw new \RuntimeException() inside tearDown() does not stop the fix, because the visitor skips the arrow function.
A setUp() with a docblock, #[\Override] and a trailing comment keeps them. The call goes in before the first statement.
A minor point: the fix splits a one-line body over two lines. protected function tearDown(): void { $this->x = null; } ends with parent::tearDown(); } on a new line. The code is valid.
testFix fails without the change in the rule and passes with it. On 6036e8e the tests (99), PHPStan and phpcs pass, and CI is green. I could not run parallel-lint locally.
Performance: I analysed 1,500 generated test classes at level 0, 6 runs each.
Every tearDown() without the parent call: 8.23 s on 2.1.x and 9.49 s with this PR, with 54.1 s against 41.6 s user CPU. Without the fixNode() call, the PR takes 8.33 s. So the cost comes from making the error fixable, about 8 ms of CPU for each error.
Every class with both parent calls: 8.54 s and 8.53 s, so no difference when there is no error.
One gap, the same kind as the throw case: a tearDown() that ends in a call that never returns still gets the call appended.
such a test is a fatal error in PHPUnit:
➜ phpunit git:(main) ✗ cat MyTest.php
<?php
class MyTest extends \PHPUnit\Framework\TestCase {
publicfunctiontestFoo() {
}
publicfunctiontearDown(): void
{
exit();
}
}
➜ phpunit git:(main) ✗ php phpunit MyTest.php
PHPUnit 14.0-g9a67d9ff4e by Sebastian Bergmann and contributors.
Runtime: PHP8.5.12
Configuration: /Users/m.staab/dvl/phpunit/phpunit.xml
Fatal error: Premature end of PHP process when running MyTest::testFoo.
therefore I don't think its worth adding separate logic for it
A minor point: the fix splits a one-line body over two lines. protected function tearDown(): void { $this->x = null; } ends with parent::tearDown(); } on a new line. The code is valid.
I think this is a code-style thing which should php-cs-fixer or similar to should take care of after phpstan-fixing finished.
What's the logic with parent setUp being called first, and parent tearDown being called last?
the idea is that the base-class usually will do basic things and the concrete subclass will do more specific things.
therefore we setups the basis first and do the specific thing later (at setUp stage).
and on teardown we do it in reverse order. undo all the specific things first and do the more basic teardown last.
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
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.
when adding a new
setUportearDownmethod into a test-case base class, you get easily a lot ofphpstan-phpuniterrors in test-cases like:my idea is to add a
parent::setUp()calls as a first statement into the existing setup method, and intearDownI think we should appendparent::tearDownto the very end of the existingtearDown.