💯

node:test と ESLint RuleTester の組み合わせ方

に公開

ESLint の RuleTester を Node.js 組み込みテストランナー(node:test)で動かすための方法をまとめる。

やりたいこと

  • Node.js 組み込みテストランナー node:testnode --test)を使う
  • 既存の RuleTester.run() の書き方はそのまま使う(valid / invalid のオブジェクトでテストを書く)

なぜわざわざ node:test を使うのかって?ロマンですよロマン。

▼「Node.js 組み込みテストランナー」って、何?って人は以下の記事を参照してください。

https://developers.play.jp/entry/2025/08/15/202214

https://nodejs.org/docs/latest/api/test.html#test-runner

ツールバージョン

手順

1. テスト実行前に RuleTesternode:test を繋ぎ込む

--import で、テストファイルよりも先に読み込んで実行する「セットアップ用スクリプト」を指定する。

package.json
{
  "scripts": {
    "test": "node --import ./test-setup.mts --test"
  }
}
  • --import ./test-setup.mts: テスト実行前に test-setup.mts を 1 回ロードする
  • --test: Node の組み込みテストランナーで *.test.* / *.spec.* を検出して実行する

2. test-setup.mts で RuleTester の describe / it を差し替える

RuleTester は内部で describeit を呼ぶ。ここを node:test の API に差し替える。

test-setup.mts
import { RuleTester } from 'eslint';
import * as test from 'node:test';

RuleTester.describe = test.describe;
RuleTester.it = test.it;
RuleTester.itOnly = test.it.only;
  • RuleTester.it / RuleTester.describe / RuleTester.itOnly を、それぞれ node:testit / describe / it.only に差し替える。
    • 依存性の注入みたいな感じ

3. テストファイルは従来どおり RuleTester.run() で書く

各ルール用の *.test.mts では、RuleTester の通常の使い方のままでよい。

my-rule.test.mts
import { RuleTester } from 'eslint';
import myRule from './my-rule.mjs';

const ruleTester = new RuleTester({
  /* 略  */
});

ruleTester.run('my-rule-name', myRule, {
  valid: [
    /* 略 */
  ],
  invalid: [
    /* 略 */
  ],
});

セットアップで RuleTester.it / RuleTester.describe を差し替えているので、この run() から呼ばれるテストはすべて node:test を通じて実行される。

まとめ

  • 実行コマンド:
    node --import ./test-setup.mts --test で「セットアップ読み込み → node:test でテスト検出・実行」
  • セットアップ:
    RuleTester の it / describe(と必要なら only)を node:test の API に差し替える
  • テストコード:
    これまで通り ruleTester.run(...) で valid / invalid を書く

この形にしておけば、追加のテストライブラリなしで、 node:testRuleTester を組み合わせて使える。


GitHub 上で同様の構成を取っているプロジェクトについて

結論: 同じ構成(node:test + RuleTester + --import で describe/it 差し替え)を取っている公開プロジェクトは、調査時点では見つかっていない。

関連する事実

  • ESLint 本体はテストに Mocha を使い続けている(公式ドキュメント)。node:test への移行は行われていない。
  • RuleTester の describe/it 差し替えは ESLint 側でサポートされている。
    • 過去に「差し替えが効かない」バグがあり、ESLint PR #15507 で修正された。
    • typescript-eslint Issue #4422 では、uvu と RuleTester を組み合わせるために RuleTester.it / RuleTester.describe を差し替える例が議論されている(node:test ではないが、同じ「別ランナーに載せる」考え方)。
  • Vitest と RuleTester を組み合わせる目的の eslint-vitest-rule-tester など、別ランナー用の RuleTester ラッパーは存在する。node:test 専用の同様パッケージは見当たらない。
  • 「node --test」と「ESLint ルールのテスト」 を同時に扱っている Issue/PR はあるが(例: nodejs/node#16138eslint-plugin-import#2603)、いずれも「node:test と RuleTester を組み合わせる」構成の事例ではない。
ゆめみ

Discussion