Skip to content

Commit 24ffb63

Browse files
[dx] add test to check that a rule is not applied if it does not change the code (#6794)
* [dx] add test to check that a rule is not applied if it does not change the code * Print warning instead of throwing an error
1 parent b92f984 commit 24ffb63

File tree

9 files changed

+125
-8
lines changed

9 files changed

+125
-8
lines changed

src/Application/FileProcessor.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,10 @@ public function processFile(File $file, Configuration $configuration): FileProce
8585
// when changed, set final status changed to true
8686
// to ensure it make sense to verify in next process when needed
8787
$file->changeHasChanged(true);
88+
}
8889

90+
$rectorWithLineChanges = $file->getRectorWithLineChanges();
91+
if ($file->hasChanged() || $rectorWithLineChanges !== []) {
8992
$currentFileDiff = $this->fileDiffFactory->createFileDiffWithLineChanges(
9093
$configuration->shouldShowDiffs(),
9194
$file,

src/Testing/PHPUnit/AbstractRectorTestCase.php

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,23 @@ protected function doTestFile(string $fixtureFilePath): void
165165
);
166166
}
167167

168+
protected function doTestFileExpectingWarningAboutRuleApplied(
169+
string $fixtureFilePath,
170+
string $expectedRuleApplied
171+
): void {
172+
ob_start();
173+
$this->doTestFile($fixtureFilePath);
174+
$content = ob_get_clean();
175+
$fixtureName = basename($fixtureFilePath);
176+
$testClass = static::class;
177+
$this->assertSame(
178+
PHP_EOL . "WARNING: On fixture file \"" . $fixtureName . '" for test "' . $testClass . "\"" . PHP_EOL .
179+
"File not changed but some Rector rules applied:" . PHP_EOL .
180+
' * ' . $expectedRuleApplied . PHP_EOL,
181+
$content
182+
);
183+
}
184+
168185
private function forgetRectorsRules(): void
169186
{
170187
$rectorConfig = self::getContainer();
@@ -209,16 +226,19 @@ private function doTestFileMatchesExpectedContent(
209226
$fixtureFilename = basename($fixtureFilePath);
210227
$failureMessage = sprintf('Failed on fixture file "%s"', $fixtureFilename);
211228

229+
$numAppliedRectorClasses = count($rectorTestResult->getAppliedRectorClasses());
212230
// give more context about used rules in case of set testing
213-
if (count($rectorTestResult->getAppliedRectorClasses()) > 1) {
214-
$failureMessage .= PHP_EOL . PHP_EOL;
215-
$failureMessage .= 'Applied Rector rules:' . PHP_EOL;
216-
231+
$appliedRulesList = '';
232+
if ($numAppliedRectorClasses > 0) {
217233
foreach ($rectorTestResult->getAppliedRectorClasses() as $appliedRectorClass) {
218-
$failureMessage .= ' * ' . $appliedRectorClass . PHP_EOL;
234+
$appliedRulesList .= ' * ' . $appliedRectorClass . PHP_EOL;
219235
}
220236
}
221237

238+
if ($numAppliedRectorClasses > 1) {
239+
$failureMessage .= PHP_EOL . PHP_EOL . 'Applied Rector rules:' . PHP_EOL . $appliedRulesList;
240+
}
241+
222242
try {
223243
$this->assertSame($expectedFileContents, $changedContents, $failureMessage);
224244
} catch (ExpectationFailedException) {
@@ -227,6 +247,16 @@ private function doTestFileMatchesExpectedContent(
227247
// if not exact match, check the regex version (useful for generated hashes/uuids in the code)
228248
$this->assertStringMatchesFormat($expectedFileContents, $changedContents, $failureMessage);
229249
}
250+
251+
if ($inputFileContents === $expectedFileContents && $numAppliedRectorClasses > 0) {
252+
$failureMessage = PHP_EOL . sprintf(
253+
'WARNING: On fixture file "%s" for test "%s"',
254+
$fixtureFilename,
255+
static::class
256+
) . PHP_EOL
257+
. 'File not changed but some Rector rules applied:' . PHP_EOL . $appliedRulesList;
258+
echo $failureMessage;
259+
}
230260
}
231261

232262
private function processFilePath(string $filePath): RectorTestResult

src/Testing/PHPUnit/ValueObject/RectorTestResult.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ public function getAppliedRectorClasses(): array
3030
{
3131
$rectorClasses = [];
3232

33-
foreach ($this->processResult->getFileDiffs() as $fileDiff) {
33+
foreach ($this->processResult->getFileDiffs(false) as $fileDiff) {
3434
$rectorClasses = array_merge($rectorClasses, $fileDiff->getRectorClasses());
3535
}
3636

src/ValueObject/ProcessResult.php

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,12 @@ public function getSystemErrors(): array
3333
/**
3434
* @return FileDiff[]
3535
*/
36-
public function getFileDiffs(): array
36+
public function getFileDiffs(bool $onlyWithChanges = true): array
3737
{
38+
if ($onlyWithChanges) {
39+
return array_filter($this->fileDiffs, fn (FileDiff $fileDiff): bool => $fileDiff->getDiff() !== '');
40+
}
41+
3842
return $this->fileDiffs;
3943
}
4044

tests/Issues/ScopeNotAvailable/ForeachValueScopeTest.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,14 @@
77
use Iterator;
88
use PHPUnit\Framework\Attributes\DataProvider;
99
use Rector\Testing\PHPUnit\AbstractRectorTestCase;
10+
use Rector\Tests\Issues\ScopeNotAvailable\Variable\ArrayItemForeachValueRector;
1011

1112
final class ForeachValueScopeTest extends AbstractRectorTestCase
1213
{
1314
#[DataProvider('provideData')]
1415
public function test(string $filePath): void
1516
{
16-
$this->doTestFile($filePath);
17+
$this->doTestFileExpectingWarningAboutRuleApplied($filePath, ArrayItemForeachValueRector::class);
1718
}
1819

1920
public static function provideData(): Iterator
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Rector\Tests\Testing\RectorRuleShouldNotBeApplied;
6+
7+
class NoChange
8+
{
9+
}
10+
11+
?>
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Rector\Tests\Testing\RectorRuleShouldNotBeApplied;
6+
7+
use Iterator;
8+
use PHPUnit\Framework\Attributes\DataProvider;
9+
use Rector\Testing\PHPUnit\AbstractRectorTestCase;
10+
use Rector\Tests\Testing\RectorRuleShouldNotBeApplied\Source\NoChangeRector;
11+
12+
final class RectorRuleShouldNotBeAppliedTest extends AbstractRectorTestCase
13+
{
14+
#[DataProvider('provideData')]
15+
public function test(string $filePath): void
16+
{
17+
$this->doTestFileExpectingWarningAboutRuleApplied($filePath, NoChangeRector::class);
18+
}
19+
20+
public static function provideData(): Iterator
21+
{
22+
return self::yieldFilesFromDirectory(__DIR__ . '/Fixture');
23+
}
24+
25+
public function provideConfigFilePath(): string
26+
{
27+
return __DIR__ . '/config/configured_rule.php';
28+
}
29+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Rector\Tests\Testing\RectorRuleShouldNotBeApplied\Source;
6+
7+
use PhpParser\Node;
8+
use PhpParser\Node\Stmt\Class_;
9+
use Rector\Rector\AbstractRector;
10+
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
11+
12+
final class NoChangeRector extends AbstractRector
13+
{
14+
public function getRuleDefinition(): RuleDefinition
15+
{
16+
return new RuleDefinition('no change', []);
17+
}
18+
19+
public function getNodeTypes(): array
20+
{
21+
return [
22+
Class_::class,
23+
];
24+
}
25+
26+
public function refactor(Node $node)
27+
{
28+
return $node;
29+
}
30+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
use Rector\Config\RectorConfig;
6+
use Rector\Tests\Testing\RectorRuleShouldNotBeApplied\Source\NoChangeRector;
7+
8+
return RectorConfig::configure()
9+
->withRules([NoChangeRector::class]);

0 commit comments

Comments
 (0)