ESLintカスタムルールの「テスト」を極める:あなたのコード品質を守る「番人」を、さらに厳格に鍛え上げる方法
こんにちは。開発環境の深淵を歩むエンジニアの皆さん。
私たちは普段、ESLintやPrettierを使ってコードを自動的に整え、ミスを未然に防いでいますよね。「コードが汚い」と怒られることに慣れきっているかもしれませんが、ふと立ち止まって考えてみてください。「そのルール自体が、もし間違っていたら?」あるいは、「特定のパターンで誤検知を起こしていたら?」
プロジェクトが巨大化し、チームが拡大するほど、カスタムルールによる「独自のコーディング規約」の強制は強力な武器になります。しかし、そのルール自体がテストされていなければ、それは「信頼できないセキュリティゲート」を通行しているのと同じことです。
今日は、ESLint公式が提供する最強の兵器『RuleTester』を使って、あなただけのカスタムルールを「鉄壁」にする方法を伝授します。これをマスターすれば、あなたは単なるツールの利用者から、チームの開発生産性を支配する「アーキテクト」へと進化できます。
—
1. なぜ「ルールのテスト」が必要なのか?
ESLintのカスタムルールは、多くの場合「AST(抽象構文木)」という、コードをコンピュータが理解できる木構造に分解して解析します。
このロジックに少しでも穴があると、以下のような悲劇が起きます。
- False Positive(誤検知): 正しいコードなのにエラーが出てしまい、開発者のやる気を削ぐ。
- False Negative(見逃し): 守るべきルールを破っているのに、エラーが出ずバグが混入する。
RuleTesterは、このAST解析のロジックが「意図通りに動いているか」を、Jestなどのテストフレームワーク上で検証するための公式ユーティリティです。
—
2. 環境構築:最小構成で最大の効果を
まず、カスタムルール開発のための最小構成を用意しましょう。特別な複雑なフレームワークは不要です。Node.js環境があればすぐに始められます。
プロジェクトの初期化
npm init -y
ESLint本体と、テストに必要なパッケージをインストール
npm install –save-dev eslint mocha
ここで重要なのは、「ルール自体はただのJavaScript関数である」という点です。特別な魔法はありません。
—
3. HelloWorld:RuleTesterで「絶対守らせたいルール」をテストする
例えば、「`console.log` を使ってはならない」という極めて単純なルールを例にします。これをテストコードで記述してみましょう。
// rule-tester.test.js
const { RuleTester } = require(“eslint”);
const rule = require(“./my-custom-rule”); // 自作ルールを読み込む
const ruleTester = new RuleTester({
// テスト環境の構成(ES6以上を使うなら必須)
parserOptions: { ecmaVersion: 2020 }
});
ruleTester.run(“no-console-log”, rule, {
// 正常系:エラーにならないはずのコード
valid: [
“const a = 1;”,
“alert(‘hello’);”
],
// 異常系:エラーになるはずのコード
invalid: [
{
code: “console.log(‘debug’);”,
errors: [{ message: “console.logは禁止です” }] // 期待されるエラー内容
}
]
});
ここが技術の肝:テストの設計思想
- `valid` にはエッジケースを詰め込む: 単純なパターンだけでなく、テンプレートリテラルや、変数名に `console` が含まれる場合など、「紛らわしいコード」をあえて記述します。
- `invalid` では期待値を厳格に: 単にエラーが出ればいいのではなく、`message` が正しいか、さらには `type`(どのトークンでエラーが出るか)まで指定することで、ルールが「意図した箇所で」働いていることを保証します。
—
4. 現場で震えるほど役立つ「設計術」:負けないルールを作る
単にテストを書くだけでなく、以下の設計を意識してください。これがプロのアーキテクトの仕事です。
A. 境界値分析(Boundary Value Analysis)
ASTを解析する際、「条件分岐の深さ」や「ネストの深さ」が境界になります。
- ルールが `IfStatement` を監視しているなら、単一の `if` だけでなく、`if-else if-else` や、`nested if` の全パターンを `valid/invalid` に網羅してください。
B. リファクタリング耐性
ルールが特定の変数名に依存していないか確認してください。テストケースに異なる変数名や関数名のパターンを混ぜることで、ルールが「汎用的」であることを保証します。
C. パフォーマンスの視点
カスタムルールが重い正規表現(Backtrackingが発生するものなど)を使っていると、CI/CDで数千ファイルの解析が止まります。テストコードの実行時間に注目し、極端に遅いテストがあればルールの設計を見直すサインです。
—
5. まとめ:なぜこれをやるのか?
「ルールをテストする」という行為は、一見すると面倒な「コスト」に見えます。しかし、これは「将来発生するであろう、数千行の修正と数時間のデバッグを、今この瞬間に数行のコードで予約消去する」という、極めて投資対効果の高いアーキテクチャ設計なのです。
あなたが記述したテストケースは、チームにとっての「守護神」となります。新しいメンバーがルールに疑問を持ったとき、テストコードを見れば「なぜこのルールが存在するのか」「どこまでが許容されるのか」が一目で理解できます。
さあ、あなたのプロジェクトに、信頼という名の規律を導入しましょう。毎日のコーディングが、今よりもずっと静かで、平和なものになるはずですよ。
—
追伸:
もし、もっと複雑なAST操作(Node間の親子関係の検証など)が必要になったら、[AST Explorer](https://astexplorer.net/) を横に置いてテストを書いてみてください。コードが木構造としてどう見えているかを可視化するだけで、テストケースの書き方が劇的に変わります。頑張ってくださいね。