Action Cable の JavaScript テストを Web Test Runner に移行
Action Cable のフロントエンドテストは、Karma から Web Test Runner へ置き換えられ、Sauce Labs 連携が新しいモジュールに統合されました。テストの振る舞いは変更せず、保守が継続されるツールチェーンへ移行した点が主旨です。
背景
Karma が公式に Deprecated とされ、バグ修正や新機能の受け入れが行われなくなっています。既存の actioncable/karma.conf.js にはブラウザ設定や Sauce Labs 用ランチャーがハードコードされており、CI で観測されるフレークの根本的な対処が困難でした。PR の説明は、メンテナンスが停止したツールチェーンから脱却し、安定した実行基盤を確保したいと述べています。
-const config = {
- browsers: ["ChromeHeadless"],
- frameworks: ["qunit"],
- files: ["test/javascript/compiled/test.js"],
- client: { clearContext: false, qunit: { showUI: true } },
- singleRun: true,
- autoWatch: false,
- captureTimeout: 180000,
- browserDisconnectTimeout: 180000,
- browserDisconnectTolerance: 3,
- browserNoActivityTimeout: 300000,
-}
-
-if (process.env.CI) {
- config.customLaunchers = {
- sl_chrome: sauce("chrome", 70),
- sl_ff: sauce("firefox", 63),
- sl_safari: sauce("safari", "16", "macOS 13"),
- sl_edge: sauce("microsoftedge", "latest", "Windows 11"),
- }
- config.browsers = Object.keys(config.customLaunchers)
- config.reporters = ["dots", "saucelabs"]
- config.sauceLabs = { testName: "ActionCable JS Client", retryLimit: 3, build: buildId() }
- function sauce(browserName, version, platform) { /* 省略 */ }
-}
上記の削除に伴い、Karma 固有の設定ファイルはリポジトリから完全に除去されました。
技術的な変更
依存関係は actioncable/package.json で大幅に入れ替えられ、@web/test-runner 系列と web-test-runner-qunit が追加され、従来の karma 系列が削除されています。変更点は次の通りです。
@@ -27,24 +27,23 @@
- "karma": "^6.4.2",
- "karma-chrome-launcher": "^2.2.0",
- "karma-qunit": "^2.1.0",
- "karma-sauce-launcher": "^1.2.0",
+ "@web/test-runner": "^0.20.2",
+ "@web/test-runner-saucelabs": "^0.13.0",
@@
- "qunit": "^2.8.0",
+ "qunit": "^2.20.0",
@@
- "test": "karma start"
+ "test": "node test/javascript/run_web_test_runner.mjs"
テスト実行エントリーポイントとして actioncable/test/javascript/run_web_test_runner.mjs が新規追加され、@web/test-runner の startTestRunner を呼び出して web-test-runner.config.mjs を指定します。コードは以下の通りです。
+/* global process */
+
+import { startTestRunner } from "@web/test-runner"
+import { classifyRun } from "./sauce_labs.mjs"
+
+const argv = ["--config", "web-test-runner.config.mjs", ...process.argv.slice(2)]
+
+startTestRunner({ autoExitProcess: false, argv }).then((runner) => {
+ if (!runner) return
+ process.on("SIGINT", () => runner.stop())
+ process.on("SIGTERM", () => runner.stop())
+ runner.on("stopped", (passed) => {
+ const sessions = Array.from(runner.sessions.all())
+ const { exitStatus, reason } = classifyRun(passed, sessions)
+ if (exitStatus !== 0) console.error(`Action Cable JavaScript tests failed: ${reason}`)
+ process.exit(exitStatus)
+ })
+})
Sauce Labs 連携ロジックは actioncable/test/javascript/sauce_labs.mjs に集約され、ランチャー生成と実行結果の分類関数を提供します。主に createSauceLabsLauncher と classifyRun がエクスポートされ、インフラ障害や WebDriver エラーを判別して終了コードを決定します。
+export const SAUCE_INFRASTRUCTURE_EXIT_STATUS = 3
+export function createSauceLabsLauncher(saucelabsOptions, saucelabsCapabilities, sauceConnectOptions) { /* 省略 */ }
+export function classifyRun(passed, sessions) { /* 省略 */ }
Web Test Runner の設定は actioncable/web-test-runner.config.mjs に記述され、テスト対象ファイル、タイムアウト、使用フレームワークとして web-test-runner-qunit を指定しています。CI 環境下では Sauce Labs 用ランチャーを組み込み、ローカル実行時はローカルブラウザが利用されます。
+/* global process */
+import { createRequire } from "module"
+import { createSauceLabsLauncher } from "./test/javascript/sauce_labs.mjs"
+const require = createRequire(`${process.cwd()}/web-test-runner.config.mjs`)
+const config = {
+ rootDir: "..",
+ files: "test/javascript/compiled/test.js",
+ nodeResolve: true,
+ browserStartTimeout: 180000,
+ testsStartTimeout: 180000,
+ testsFinishTimeout: 300000,
+ testFramework: { path: require.resolve("web-test-runner-qunit"), config: {} },
+}
+if (process.env.CI) {
+ const sauce = createSauceLabsLauncher({ user: process.env.SAUCE_USERNAME, key: process.env.SAUCE_ACCESS_KEY, region: "us" }, { build: buildId(), name: "ActionCable JS Client" })
+ config.browsers = [
+ sauce({ browserName: "chrome", browserVersion: "98", platformName: "Windows 10", "wdio:enforceWebDriverClassic": true }),
+ sauce({ browserName: "firefox", browserVersion: "94", platformName: "Windows 10", "wdio:enforceWebDriverClassic": true }),
+ // Safari 省略
+ ]
+}
+export default config
以上の変更により、テスト実行フローは Karma → Web Test Runner へシフトし、npm test の呼び出しだけで同等のテストが走ります。
設計判断
テストランナー全体の置き換えが採用された理由は、メンテナンスが停止したツールに依存し続けるリスクを回避し、同一のテストコードと QUnit フレームワークをそのまま利用できる点にあります。PR の記述は「フレークの根本的な対処はツールチェーンの変更で容易になる」と示唆しており、実装も CI 条件 (process.env.CI) や Sauce Labs 設定を従来と同様に保持しています。
後方互換性は package.json の scripts.test だけを変更し、テスト対象ファイルや QUnit の使用方法は変更していないため、開発者がテストコードを修正する必要はありません。新しい設定ファイルはランナー固有ですが、プロジェクト外部からは影響が見えにくい構造となっています。
トレードオフとしては、@web/test-runner 系列の依存が追加され、設定ファイルの管理コストが増加する点が挙げられます。一方で、公式にメンテナンスが続くツールを採用することで、長期的な保守性と拡張性が向上すると判断されています。
まとめ
Action Cable の JavaScript テストは Karma から Web Test Runner へ移行し、Sauce Labs 連携ロジックを新モジュールに集約しました。テストの振る舞いはそのままで、メンテナンスが停止したツールへの依存を除去し、安定した実行基盤を提供します。