3.4 KiB
How to Add Test for Rector Rule
1. Detect the Rector Rule
Run Rector only on 1 directory, or better 1 file.
vendor/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.
2. Detect the Minimal File
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
a put only the broken line there.
In our case, all we need is:
class StaticEasyPrefixer
{
}
Then rerun Rector to confirm:
vendor/bin/rector process app/SomeFile.php
Do we have the same diff? Great!
3. Find the Rector Test Case
Now we need to find the test case. The test case name is rule + Test
suffix.
FinalizeClassesWithoutChildrenRector
↓
FinalizeClassesWithoutChildrenRectorTest
(test class)
↓
FinalizeClassesWithoutChildrenRectorTest.php
(test file)
Right here:
4. Add Change or No-Change Test Fixture File
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.
1. The Code Should Change
<code before>
-----
<code after>
2. The Code Should Be Skipped
<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
{
}
?>
- The closing
?>
is there for slightly better PHPStorm. - The PSR-4 namespace is there to make each class unique because the test classes are loaded to an analysis by reflection and must be unique
- The file name conventions => class is
add_final.php.inc
=>AddFinal
class
Run 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! :)