Whenever you encounter a situation where Rector does not behave as expected, please create a pull request with a test case that shows what you expected and rector misbehaving. When someone is working on fixing this issue, the test case will make it easy to see whether the issue is actually fixed.
When using Rector to update your own code, you will typically be using release repository installed by composer, however, when adding tests, you will need to use the development repository as shown:
composer install
composer fix-cs
and composer phpstan
bin/rector
instead of the typical vendor/bin/rector
Run Rector only on 1 directory, or better 1 file.
bin/rector process /some-file.php
See "Applied rules" under the diff:
Our rule in this example is: Rector\Privatization\Rector\Class_\FinalizeClassesWithoutChildrenRector
This rule's job is to add final
to every class that has no children and is not a Doctrine entity = everywhere it can without breaking our code.
Usually, the Rector diff output is long and contains many other errors related to other rules. It's a mess; we can't use that for a test fixture. We need to find 1 responsible line.
The best way is to copy the file to local code, e.g. app/SomeFile.php
and put only the broken line there.
In our case, all we need is:
class StaticEasyPrefixer
{
}
Then rerun Rector to confirm:
bin/rector process app/SomeFile.php
Do we have the same diff? Great!
Now we need to find the test case. The test case name is rule + Test
suffix.
FinalizeClassesWithoutChildrenRector
↓
FinalizeClassesWithoutChildrenRectorTest
(test class)
Right here:
Next to the test case, there is /Fixture
directory. It contains many test fixture files that verified the Rector rule work correctly in all possible cases.
Do you see test fixture file first time? It's a file with real-life PHP code that test 1 specific case that rule should cover or avoid. E.g., one test fixture file can contain a Doctrine entity that cannot be final and should be skipped by this rule. By convention, the first fixture file has the name fixture.php.inc
.
In the /Fixture
directory, we create our test fixture file, e.g., add_final.php.inc
. The .php.inc
is there on purpose, so the file is hidden from coding standard tools and static analysis.
There are 2 fixture formats:
<code before>
-----
<code after>
<code before>
In this particular case, the code should change - final
should be added so that the test fixture would look like this:
<?php
namespace Rector\Tests\Privatization\Rector\Class_\FinalizeClassesWithoutChildrenRector\Fixture;
class AddFinal
{
}
?>
-----
<?php
namespace Rector\Tests\Privatization\Rector\Class_\FinalizeClassesWithoutChildrenRector\Fixture;
final class AddFinal
{
}
?>
?>
is there for slightly better PHPStorm.add_final.php.inc
=> AddFinal
classRun PHPUnit with the test file to confirm:
vendor/bin/phpunit rules-tests/Privatization/Rector/Class_/FinalizeClassesWithoutChildrenRector/FinalizeClassesWithoutChildrenRectorTest.php
To run only the single test fixture, add --filter test#X
, where X is the fixture's order number.
vendor/bin/phpunit rules-tests/Privatization/Rector/Class_/FinalizeClassesWithoutChildrenRector/FinalizeClassesWithoutChildrenRectorTest.php --filter test#4
If PHPUnit fails, you've successfully added a test case! :)
Thank you