-
-
Notifications
You must be signed in to change notification settings - Fork 414
[dx] add test to check that a rule is not applied if it does not change the code #6794
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
...s/Rector/FuncCall/FunctionArgumentDefaultValueReplacerRector/Fixture/version_compare.php.inc
Outdated
Show resolved
Hide resolved
rules-tests/Php70/Rector/FuncCall/MultiDirnameRector/Fixture/fixture.php.inc
Outdated
Show resolved
Hide resolved
rules-tests/Php70/Rector/FuncCall/MultiDirnameRector/Fixture/skip.php.inc
Show resolved
Hide resolved
rules/CodeQuality/Rector/If_/ConsecutiveNullCompareReturnsToNullCoalesceQueueRector.php
Show resolved
Hide resolved
rules/TypeDeclaration/Rector/ClassMethod/AddParamTypeBasedOnPHPUnitDataProviderRector.php
Show resolved
Hide resolved
rules/TypeDeclaration/Rector/ClassMethod/AddParamTypeBasedOnPHPUnitDataProviderRector.php
Show resolved
Hide resolved
rules/TypeDeclaration/Rector/ClassMethod/AddReturnArrayDocblockBasedOnArrayMapRector.php
Show resolved
Hide resolved
rules/TypeDeclaration/Rector/ClassMethod/ParamTypeByMethodCallTypeRector.php
Show resolved
Hide resolved
$file->changeHasChanged(true); | ||
} | ||
|
||
$rectorWithLineChanges = $file->getRectorWithLineChanges(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we have applied any rector rule, we create a FileDiff object even if the code has not actually changed. This FileDiff object will have an empty diff.
$this->assertStringMatchesFormat($expectedFileContents, $changedContents, $failureMessage); | ||
} | ||
|
||
if ($inputFileContents === $expectedFileContents && $numAppliedRectorClasses > 0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we expect that the code should not change but there has been any Rector rule applied then we throw an error to let the user know that this is incorrect
$rectorClasses = []; | ||
|
||
foreach ($this->processResult->getFileDiffs() as $fileDiff) { | ||
foreach ($this->processResult->getFileDiffs(false) as $fileDiff) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here we want to get all file diffs, including those where there was no actual change
* @return FileDiff[] | ||
*/ | ||
public function getFileDiffs(): array | ||
public function getFileDiffs(bool $onlyWithChanges = true): array |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In most cases we will just be interested in the file diffs where there was an actual change, so we filter out those where there was no change recorded
#[DataProvider('provideData')] | ||
public function test(string $filePath): void | ||
{ | ||
$this->expectException(RectorRuleShouldNotBeAppliedException::class); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In this particular test, the refactor() function returns on purpose a Node element even though it does not change it. This is done to confirm that the code that handles this node does not throw an error. So in this particular case we need to confirm that we know that this rule would be applied even though it does not change the code
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
use ob_start()
and ob_get_clean()
to get echo warning should be the way on this on purpose test
#[DataProvider('provideData')] | ||
public function test(string $filePath): void | ||
{ | ||
$this->expectException(RectorRuleShouldNotBeAppliedException::class); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To test the new functionality we run a rule that returns a Node even though it does not change it and then we confirm that we catch this case and throw an exception informing us of the problem
Thanks for the PR 👍 It seems quite heavy to review. |
@TomasVotruba I can separate the fixes to the existing tests from the actual new test that revealed them, let me do that |
I have created some PRs, need to leave now, will continue tomorrow |
22e34d9
to
c6fc91c
Compare
@TomasVotruba now that all the changes to the existing rules have been merged I have rebased this PR to only leave the changes for the new test |
if ($inputFileContents === $expectedFileContents && $numAppliedRectorClasses > 0) { | ||
$failureMessage = $fixtureNameMessage . PHP_EOL . PHP_EOL | ||
. 'File not changed but some Rector rules applied:' . PHP_EOL . $appliedRulesList; | ||
throw new RectorRuleShouldNotBeAppliedException($failureMessage); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I prefer symfony warning instead of throw to make less noise or make return on purpose on test
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @samsonasik, not sure I understand what you mean, can you provide some example code?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just simple echo seems enough:
echo 'File not changed but some Rector rules applied:' . PHP_EOL . $appliedRulesList . PHP_EOL,
Actually, there is SymfonyStyle
service, but seems skipped under unit test
rector-src/src/Console/Command/ProcessCommand.php
Lines 111 to 115 in 9939bd2
$this->symfonyStyle->warning(sprintf( | |
'These rules are registered in both sets and "withRules()". Remove them from "withRules()" to avoid duplications: %s* %s', | |
PHP_EOL . PHP_EOL, | |
implode(' * ', $setAndRulesDuplicatedRegistrations) . PHP_EOL | |
)); |
so only e2e test can show the warning.
87ccdff
to
db8a1b2
Compare
@samsonasik I have updated the code to print a warning instead of throwing an error, you can see how it looks here, for example: https://github.com/rectorphp/rector-src/actions/runs/13995973300/job/39191131180?pr=6794 |
Looks good 👍
Test keep running ok so we can continue improve while wait for improving on the rector rules 👍 |
This may need verify on changed by DocblockUpdater service, which change the comment attribute |
I don't think this would be a problem. Even if the DocblockUpdater updates the comments, this would either change the final code of the file or not. If it does not change it and we have a test that checks that it does not change and a rule is applied, then we flag this as a warning. Any other case is ignored by this code |
I checked on rector-symfony rules, it seems somehow change docblock not really detected, which may need to be verified more... |
Mmm, let me test this over the weekend, I'll let you know |
@samsonasik I tested the rector-symfony repo with this code and I could not see any case of docblock change not detected. I fixed all the cases detected by this PR and created another PR in that repo rectorphp/rector-symfony#711 so from my side I am not seeing anything that does not work as expected. If you still see some issues, can you please provide more information? Thanks! |
While working on the Doctrine repo changes I realised that we need to change the |
Yes, separate PR would be better 👍 |
bb69d12
to
e2c1143
Compare
OK, moved to a new PR #6813 |
e2c1143
to
fa7c0c8
Compare
@TomasVotruba @samsonasik all the issues in the rector/* repos have now been fixed so this should be ready to go if you believe it is OK |
I am restarting packages tests to see if no longer warning in tests |
package tests seems still have warnings, ref https://github.com/rectorphp/rector-src/actions/runs/14168592413/job/40439865009?pr=6794 |
It seeems ok now, let's give it a try, thank you @carlos-granados |
Thank you @carlos-granados 🥳 |
In several cases we have found previously that a rule was applied (it returned a Node object from the
refactor()
method) even when it had not actually changed the code. A couple of examples:This generates two problems:
In this PR we implement a fail-safe check that applies to all our tests where we test that a file has not changed. If in this case we detect that a rule has been applied, then we make this test fail so that this kind of problems can be detected early while the rule is in development.
This PR also fixes several cases in our current tests which had this problem.
If this gets accepted, I will work to fix similar cases in the rector-symfony, rector-doctrine, rector-phpunit and rector-downgrade-php repos