|
| 1 | +- Start Date: 2019-06-07 |
| 2 | +- RFC PR: https://github.com/eslint/rfcs/pull/25 |
| 3 | +- Authors: Toru Nagashima ([@mysticatea](https://github.com/mysticatea)) |
| 4 | + |
| 5 | +# `RuleTester` Improvements |
| 6 | + |
| 7 | +## Summary |
| 8 | + |
| 9 | +This RFC improves `RuleTester` to check more mistakes. |
| 10 | + |
| 11 | +## Motivation |
| 12 | + |
| 13 | +`RuleTester` overlooks some mistakes. |
| 14 | + |
| 15 | +- Using non-standard properties of AST ([typescript-eslint/typescript-eslint#405](https://github.com/typescript-eslint/typescript-eslint/issues/405)).<br> |
| 16 | + Especially, `node.start` and `node.end` exist in AST `espree` made, but it's not standardized and some custom parsers don't make those properties. But `node.loc` has `start`/`end` properties, so it's hard to detect `node.start`/`node.end` with static analysis. Therefore, `RuleTester` should detect those. |
| 17 | +- Untested autofix.<br> |
| 18 | + If people forgot to write `output` property in test cases, `RuleTester` doesn't test autofix silently. |
| 19 | +- `errors` property with a number (found in [eslint/eslint#11798](https://github.com/eslint/eslint/pull/11798)).<br> |
| 20 | + `errors` property with a number ignores syntax errors in test code. We overlooked the mistake of [tests/lib/rules/complexity.js#L84](https://github.com/eslint/eslint/blob/cb1922bdc07e58de0e55c13fd992dd8faf3292a4/tests/lib/rules/complexity.js#L84) due to this. The number `errors` property cannot check the reported error was the expected error. |
| 21 | +- Typo property names in `errors` property with objects.<br> |
| 22 | + [eslint/eslint#12096](https://github.com/eslint/eslint/pull/12096). |
| 23 | + |
| 24 | +## Detailed Design |
| 25 | + |
| 26 | +1. Disallowing `node.start` and `node.end` |
| 27 | +1. Ensuring to test autofix |
| 28 | +1. Changing the `errors` property of a number to fail on syntax errors |
| 29 | +1. Changing the `errors` property of objects to fail on unknown properties |
| 30 | + |
| 31 | +### 1. Disallowing `node.start` and `node.end` |
| 32 | + |
| 33 | +`RuleTester` fails test cases if a rule implementation used `node.start` or `node.end` in the test case. |
| 34 | + |
| 35 | +#### Implementation |
| 36 | + |
| 37 | +- In `RuleTester`, it registers an internal custom parser that wraps `espree` or the parser of `item.parser` to `Linter` object. |
| 38 | +- The internal custom parser fixes the AST that the original parser returned, as like [test-parser.js](https://github.com/eslint/eslint/blob/21f3131aa1636afa8e5c01053e0e870f968425b1/tools/internal-testers/test-parser.js). |
| 39 | + |
| 40 | +### 2. Ensuring to test autofix |
| 41 | + |
| 42 | +`RuleTester` fails test cases if a rule implementation fixed code but `output` property was not defined in the test case. |
| 43 | + |
| 44 | +#### Implementation |
| 45 | + |
| 46 | +- If `output` property didn't exist but the rule fixed the code, `RuleTester` fails the test case as "The rule fixed the code. Please add 'output' property." It's implemented around [lib/rule-tester/rule-tester.js#L594](https://github.com/eslint/eslint/blob/21f3131aa1636afa8e5c01053e0e870f968425b1/lib/rule-tester/rule-tester.js#L594). |
| 47 | + |
| 48 | +### 3. Changing the `errors` property of a number to fail on syntax errors |
| 49 | + |
| 50 | +`RuleTester` fails test cases always if the `code` has a syntax error. |
| 51 | + |
| 52 | +#### Implementation |
| 53 | + |
| 54 | +- Unwrap [lib/rule-tester/rule-tester.js#L414-L419](https://github.com/eslint/eslint/blob/02d7542cfd0c2e95c2222b1e9e38228f4c19df19/lib/rule-tester/rule-tester.js#L414-L419). |
| 55 | + |
| 56 | +### 4. Changing the `errors` property of objects to fail on unknown properties |
| 57 | + |
| 58 | +`RuleTester` fails test cases if any item of `errors` has unknown properties. |
| 59 | + |
| 60 | +#### Implementation |
| 61 | + |
| 62 | +- [eslint/eslint#12096](https://github.com/eslint/eslint/pull/12096) |
| 63 | + |
| 64 | +## Documentation |
| 65 | + |
| 66 | +[RuleTester](https://eslint.org/docs/developer-guide/nodejs-api#ruletester) should be updated. |
| 67 | + |
| 68 | +- `output` ("optional" → "required if the rule fixes code") |
| 69 | + |
| 70 | +## Drawbacks |
| 71 | + |
| 72 | +This change may enforce plugin owners to fix their tests. |
| 73 | + |
| 74 | +## Backwards Compatibility Analysis |
| 75 | + |
| 76 | +This is a breaking change that can break existing tests. |
| 77 | + |
| 78 | +But the breaking cases may indicate that the rule was not tested enough. |
| 79 | + |
| 80 | +## Alternatives |
| 81 | + |
| 82 | +- About "Disallowing `node.start` and `node.end`", we can standardize those properties. But it's a breaking change for custom parser owners. On the other hand, using `node.start` and `node.end` breaks the rule if users used custom parsers, so the impact of this disallowing is limited. |
| 83 | + |
| 84 | +## Related Discussions |
| 85 | + |
| 86 | +- https://github.com/eslint/eslint/issues/8956 |
| 87 | +- https://github.com/eslint/eslint/pull/8984 |
| 88 | +- https://github.com/eslint/eslint/pull/11798 |
| 89 | +- https://github.com/eslint/eslint/pull/12096 |
| 90 | +- https://github.com/typescript-eslint/typescript-eslint/issues/405 |
0 commit comments