背景:Playwrightのカバレッジ機能の限界
Playwright は現在もっとも広く使われているE2Eテストフレームワークのひとつです。しかし、公式が推奨するコードカバレッジの収集方法には根本的な制約があります。それは、テスト対象のアプリケーションがバンドルされていない素のJavaScriptで動作していることを前提としている点です。
Vite や Webpack などのビルドツールで生成されたプロダクションバンドルに対しては、Playwrightが収集した生のカバレッジデータをオリジナルのソースファイルに正確にマッピングすることができません。結果として、実際のコード実行状況を正しく反映したレポートを得ることは困難です。
既存アプローチとその限界
現在広く採用されているアプローチは、Istanbul.js のインストルメンテーションをビルドパイプラインに直接組み込む方法です。インストルメンテーションの設定 → Playwrightテストの実行 → カバレッジデータの収集 → コマンドラインによるレポート生成、という流れで進みます。
しかしこのワークフローは、実際の現場では同時に満たすことが難しい、ふたつの前提条件に依存しています。
前提条件1:テストとソースコードが同一リポジトリに存在すること。 Istanbul.jsはローカルファイルシステム上のファイルを参照してシンボルを解決します。E2EテストスイートがフロントエンドプロジェクトとA別のリポジトリにある場合、レポートの生成自体が行えません。
前提条件2:テストが自動化されていること。 実際には、すべてのフロントエンドコードベースが成熟したCI/CDパイプラインを備えた整然としたオープンソースプロジェクトのようなわけではありません。企業内のUIオートメーションプラットフォームでは、テストスイートとフロントエンドプロジェクトが完全に分離して管理されているケースも多くあります。さらによくある状況として、自動化テストが存在せず、品質保証をすべて手動テストに頼っているチームも少なくありません。
Canyon は、こうした課題を解決するために開発されました。
Canyonの設計思想
CanyonはIstanbul.jsの実績あるASTインストルメンテーションエンジンを基盤としています。ビルド時にIstanbul.jsがJavaScriptの構文木を解析し、すべての文・関数・分岐の先頭に実行カウンターを埋め込むことで、実行時にどのコードパスが通ったかを精密に記録します。
Canyonはこの基盤の上に、分離問題を解決するためのふたつのアプローチを実装しています。
アプローチ1:ソースコードの分離
Canyonは buildHash という仕組みを導入しており、@canyonjs/babel-plugin パッケージとして提供されています。
CIパイプラインの実行中、このプラグインは repoID と CommitSHA というふたつの重要な環境変数を読み取り、そこから導出したハッシュ値をインストルメント済みコードのカバレッジオブジェクトに埋め込みます。後からカバレッジレポートを生成する際、Canyonサーバーはこのハッシュを手がかりに GitLab API から対応バージョンのソースファイルを直接取得し、シンボルマッピングとレポートレンダリングをサーバー側で完結させます。
ソースコードはテストスイートと共存する必要がなくなります。 これが従来のアプローチとの最も本質的な違いです。
アプローチ2:分散カバレッジ収集
自動化テストではなく手動テストに依存するチームでは、カバレッジデータの発生源が本質的に分散しています。異なるテスト担当者が、異なる時刻・環境でブラウザを操作することでデータが生成されるためです。
Canyonはこの収集アーキテクチャを分散システムとして設計しています。
- ディスクバックドメッセージキュー:複数クライアントからのカバレッジレポートをバッファリングして非同期処理し、ピーク時のデータ損失を防ぎます。
- 冪等な消費処理:同一データが重複送信された場合でも、集計結果に誤差が生じません。
- 分散ロック:並行するマージ処理を直列化することで、最終的なカバレッジ状態の正確性を保証します。
これらの仕組みが連携することでカバレッジデータの鮮度と正確性が維持され、テストの進行に合わせてレポートをリアルタイムに更新することが可能です。
また、Canyonにはスナップショット機能も備わっています。任意のカバレッジタグに対してある時点のスナップショットを生成できるため、Case IDと組み合わせることで、特定のテストケースを実行した直後のカバレッジ状態を正確に再現できます。不具合の調査やカバレッジのギャップ分析において強力な手段となります。
Canyonが解決する課題
| 課題 | Canyonの解決策 |
|---|---|
| バンドル後のJSをソースにマッピングできない | Istanbul.js ASTインストルメンテーション + buildHashによるソース分離 |
| E2EテストとフロントエンドプロジェクトがAリポジトリ分離している | repoID / CommitSHAを使ってサーバーが独立してソースを取得 |
| 自動化テストがなく手動テストのみ | マルチブラウザの並行レポートに対応した分散収集アーキテクチャ |
| 収集・マージされたカバレッジデータの正確性 | ディスクキュー + 冪等な消費処理 + 分散ロック |
| 特定テストケースへのカバレッジ遡及 | Case ID単位でレポートを生成するスナップショット機能 |
まとめ
ビルド時のbuildHashインストルメンテーションと分散カバレッジ収集サービスというふたつの設計によって、Canyonはコードカバレッジの適用範囲を「同一モノリポに自動化テストが存在するチーム専用の機能」から、ほぼすべてのフロントエンド開発環境へと広げました。UIオートメーションプラットフォームを導入済みのチームであれ、手動テストを主体とするチームであれ、Canyonを通じてソースコードレベルの正確なカバレッジを把握し、テストの盲点を見つけ、バグになる前に対処することができます。
関連リンク
- Canonドキュメント:https://docs.canyonjs.io/
- Canyon GitHub:https://github.com/canyon-project/canyon