mirror of
https://github.com/rectorphp/rector.git
synced 2024-06-28 21:53:31 +00:00
[docs] How to add Rector rule test (#4364)
* [docs] How to add Rector rule test * improvements * gramarly * Update docs/how_to_add_test_for_rector_rule.md Co-authored-by: Abdul Malik Ikhsan <samsonasik@gmail.com> Co-authored-by: Abdul Malik Ikhsan <samsonasik@gmail.com>
This commit is contained in:
parent
84c03bcbdc
commit
dcad6b8862
125
docs/how_to_add_test_for_rector_rule.md
Normal file
125
docs/how_to_add_test_for_rector_rule.md
Normal file
|
@ -0,0 +1,125 @@
|
||||||
|
# How to Add Test for Rector Rule
|
||||||
|
|
||||||
|
## 1. Detect the Rector Rule
|
||||||
|
|
||||||
|
Run Rector only on 1 directory, or better 1 file.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
vendor/bin/rector process compiler/src/PhpScoper/StaticEasyPrefixer.php
|
||||||
|
```
|
||||||
|
|
||||||
|
See "Applied rules" under the diff:
|
||||||
|
|
||||||
|
![Applied Rules](/docs/images/docs_applied_rules.png)
|
||||||
|
|
||||||
|
Our rule in this example is: `Rector\SOLID\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:
|
||||||
|
|
||||||
|
```php
|
||||||
|
class StaticEasyPrefixer
|
||||||
|
{
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Then rerun Rector to confirm:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
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:
|
||||||
|
|
||||||
|
![Rule Test Case](/docs/images/docs_rule_test_case.png)
|
||||||
|
|
||||||
|
## 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
|
||||||
|
|
||||||
|
```bash
|
||||||
|
<code before>
|
||||||
|
-----
|
||||||
|
<code after>
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. The Code Should Be Skipped
|
||||||
|
|
||||||
|
```bash
|
||||||
|
<code before>
|
||||||
|
```
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
In this particular case, the code should change - `final` should be added so that the test fixture would look like this:
|
||||||
|
|
||||||
|
```php
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Rector\SOLID\Tests\Rector\Class_\FinalizeClassesWithoutChildrenRector\Fixture;
|
||||||
|
|
||||||
|
class AddFinal
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
|
-----
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Rector\SOLID\Tests\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:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
vendor/bin/phpunit rules/solid/tests/Rector/Class_/FinalizeClassesWithoutChildrenRector/FinalizeClassesWithoutChildrenRectorTest.php
|
||||||
|
```
|
||||||
|
|
||||||
|
To run only the single test fixture, add `--filter test#X`, where X is the fixture's order number.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
vendor/bin/phpunit rules/solid/tests/Rector/Class_/FinalizeClassesWithoutChildrenRector/FinalizeClassesWithoutChildrenRectorTest.php --filter test#4
|
||||||
|
```
|
||||||
|
|
||||||
|
If PHPUnit fails, you've successfully added a test case! :)
|
BIN
docs/images/docs_applied_rules.png
Normal file
BIN
docs/images/docs_applied_rules.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 23 KiB |
BIN
docs/images/docs_rule_test_case.png
Normal file
BIN
docs/images/docs_rule_test_case.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 15 KiB |
Loading…
Reference in New Issue
Block a user