Matware E2e Runner について
Matware E2e Runnerは、JSONでテストを定義し、AIによる作成・実行・デバッグを行う開発チーム向けのWeb E2Eテストツールです。並列ブラウザプール、ライブダッシュボード、課題からテストを作るフローを備えています。
主な機能
- 01JSONによるテストフロー定義
- 02MCP経由でのテスト作成と実行
- 03ブラウザテストの並列実行
- 04スクリーンショットとライブダッシュボード
- 05課題からのテスト生成と検証
活用シーン
- 01ログインや購入フローのテスト
- 02GitHubやGitLabの課題をテスト化
- 03CIでのテスト並列実行
MCP 対応
組み込みMCPサーバーが、Claude CodeなどのMCPクライアントにテスト作成・実行・デバッグ用の17個のツールを提供します。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
ツール
15掲載時のツール一覧 · 2 週間前に更新
| パラメーター | 型 | 必須 | 説明 |
|---|---|---|---|
| all | boolean | いいえ | tests ディレクトリ内のすべてのテストスイートを実行します |
| cwd | string | いいえ | プロジェクトのルートディレクトリの絶対パス。Claude Code は現在の作業ディレクトリを渡してください。 |
| file | string | いいえ | JSON テストファイルの絶対パスまたは相対パス |
| suite | string | いいえ | 実行するスイート名(例:"auth"、"01-login")。数字の接頭辞の有無にかかわらず一致します。 |
| baseUrl | string | いいえ | 今回の実行でベース URL を上書きします |
| retries | number | いいえ | 失敗したテストの再試行回数 |
| concurrency | number | いいえ | 並列ワーカー数(デフォルトは設定から取得) |
| failOnNetworkError | boolean | いいえ | ネットワークリクエストが失敗した場合(例:ERR_CONNECTION_REFUSED)にテストを失敗させます。デフォルト:false。 |
| verificationStrictness | enum | いいえ | ビジュアル検証の厳格さ。strict:曖昧さを許容せず、疑いがあれば FAIL。moderate:妥当な判断(デフォルト)。lenient:明らかな矛盾がある場合のみ失敗とします。strict | moderate | lenient |
詳細
English · スペイン語
@matware/e2e-runner
テストの作成、実行、デバッグを代わりに行う、AI ネイティブな E2E テストランナーです。
E2E Runner を使えば、テストコードを書かずにウェブアプリをテストできます。テストはプレーンな JSON 形式です。しかも、自分で書く必要すらありません。Claude Code に頼むだけです。
🎬 頼んでテストを作成し、実行を見届ける
スイートの実行中に表示されるライブダッシュボード — 各ステップのスクリーンショットがリアルタイムでフィードにストリーミングされます。
組み込みの MCP サーバーを使えば、テストの作成は会話するだけです。ドキュメントを調べたり、構文を覚えたりする必要はありません。
あなた: ログインフローの E2E テストを作成して実行して。
Claude Code: テストを作成し、実際のブラウザーで実行して、結果を報告します — ✅
login-flowが 2.3 秒で成功 · スクリーンショットを保存 · ネットワークエラーなし。
裏側では、Claude が次の内容を書いて実行しています。テストはただの JSONです。ユーザーが行う操作を順に並べたリストです。
[
{ "name": "login-flow", "actions": [
{ "type": "goto", "value": "/login" },
{ "type": "type", "selector": "#email", "value": "[email protected]" },
{ "type": "type", "selector": "#password", "value": "secret" },
{ "type": "click", "text": "Sign In" },
{ "type": "assert_text", "text": "Welcome back" },
{ "type": "screenshot", "value": "logged-in.png" }
]}
]
インポートも、describe/it も、ビルド手順もありません。読めるなら書けます。あるいは、頼むだけです。
Claude Code に接続する(2 つのコマンド):
claude plugin marketplace add fastslack/mtw-e2e-runner
claude plugin install e2e-runner@matware
あとは「X のテストを作成して実行して」と伝えるだけです。Claude は 17 個の MCP ツール、スラッシュコマンド、専門エージェントを利用できるようになります。
別のエージェント(Cursor、Codex、Copilot、その他 40 以上)を使用していますか?スキルをインストールしてください:
npx skills add fastslack/mtw-e2e-runner
📖 目次
| セクション | 内容 | |
|---|---|---|
| 🚀 | インストールと最初のテスト | npm のセットアップ · お使いの Chrome(Docker 不要)、Obscura、または Docker プールで実行 |
| ✨ | 利用できる機能 | 機能の概要 |
| ✍️ | テストの作成 | テスト形式 · アクション一覧 · 再試行 · シリアル実行 · モジュール · 認証 · フック |
| 🤖 | AI 連携 | Claude Code · OpenCode · 17 個の MCP ツール · ビジュアル検証 · 課題からテストを作成 |
| 📊 | ダッシュボードと分析 | ライブダッシュボード · 学習システム · ネットワークログ · スクリーンショットの撮影 |
| 🌐 | ブラウザードライバー | browserless · cdp · lightpanda · obscura · steel |
| ⚙️ | CLI、設定、CI | コマンド · フラグ · e2e.config.js · GitHub Actions · プログラム API |
🚀 インストール — とても小さいです
npm install --save-dev @matware/e2e-runner
npx e2e-runner init # scaffolds e2e/ with a sample test + config
次に、ブラウザーの実行方法を選びます。並列実行プールを使う場合を除き、Docker は不要です。
オプション 1 · お使いの Chrome を使用 — Docker 不要 ⭐
デバッグポートを指定して任意の Chromium ブラウザーを起動し、ランナーに接続先を指定します。
google-chrome --headless=new --remote-debugging-port=9222 & # or brave / chromium / msedge
CHROME_POOL_URL=http://localhost:9222 POOL_DRIVER=cdp npx e2e-runner run --all
または、e2e.config.js に設定して、毎回指定する手間を省きます。
export default {
baseUrl: 'http://localhost:3000', // your app — plain localhost, no docker hostname
poolUrls: ['http://localhost:9222'],
poolDriver: 'cdp',
};
npm 以外にインストールは不要で、ブラウザーはお使いのマシン上で動作するため、baseUrl には localhost を指定します。
オプション 2 · Obscura — 小さなバイナリ 1 つで、Docker 不要
検出回避機能を内蔵した約 30 MB の単一バイナリです。一度インストールして実行し、ランナーに接続先を指定します。
obscura serve --port 9222 --stealth &
CHROME_POOL_URL=http://localhost:9222 POOL_DRIVER=obscura npx e2e-runner run --all
npx e2e-runner pool start を実行すると(設定で poolDriver: 'obscura' を指定)、お使いの OS に合わせた正確なインストールコマンドが表示されます。
オプション 3 · Docker プール — 並列実行、CI や大規模なテストスイート向け
複数のテストを同時に実行する、共有のキュー管理型 Chrome プールです。
npx e2e-runner run --all # the first run auto-starts the Docker pool for you
Docker が必要です。コンテナ内の Chrome からアプリにアクセスできるよう、baseUrl: 'http://host.docker.internal:3000' を設定してください。
host.docker.internal を使う理由(Docker オプションのみ)
Docker プールでは Chrome がコンテナ内で動作するため、コンテナ内の localhost はお使いのマシンではなく、コンテナを指します。host.docker.internal を使うとホストに接続できます。Linux(Docker Desktop ではなく Docker Engine)の場合は、--add-host=host.docker.internal:host-gateway を追加するか、LAN IP を使用してください。オプション 1 と 2 ではこの設定は不要です。ブラウザーはローカルで動作するため、通常の localhost をそのまま使用できます。
最初のテストを書く
e2e/tests/sample.json を開きます。フローは、順序付けられたアクションのリストです。
[
{ "name": "homepage loads", "actions": [
{ "type": "goto", "value": "/" },
{ "type": "assert_text", "text": "Welcome" },
{ "type": "screenshot", "value": "home.png" }
]}
]
npx e2e-runner run --all で実行します。合否、所要時間、スクリーンショット、ネットワークエラーなどの結果は、ターミナルと、開いている場合はウェブダッシュボードに表示されます。
OpenCode を追加する(任意)
cp node_modules/@matware/e2e-runner/opencode.json ./
mkdir -p .opencode && cp -r node_modules/@matware/e2e-runner/.opencode/* .opencode/
詳細については、OPENCODE.md を参照してください。
更新
インストール方法ごとに個別に更新します。使用しているものを更新してください。
# npm dependency (per project)
npm install --save-dev @matware/e2e-runner@latest
# Claude Code plugin
claude plugin update e2e-runner@matware
# MCP-only install (npx caches the package — pin @latest to force a refresh)
claude mcp add --transport stdio --scope user e2e-runner \
-- npx -y -p @matware/e2e-runner@latest e2e-runner-mcp
メモ
注意点が 2 つあります。(1)
npxは自身のキャッシュよりも、プロジェクトのnode_modules内にあるコピーを優先します。プロジェクトで古いバージョンが固定されていると、MCP サーバーとダッシュボードもその古いバージョンで実行されるため、プロジェクトの依存関係も更新してください。(2) すでに実行中のプロセスは、古いコードをメモリ上に保持します。更新後はダッシュボードを再起動し、MCP サーバーに再接続してください(/mcp→e2e-runner→ Reconnect、またはセッションを再起動)。
✨ 得られるもの
🧪 コード不要のテスト — チームの誰もが読み書きできる JSON ファイルです。JavaScript もコンパイルも不要で、特定のフレームワークに縛られません。
🤖 AI を活用したテスト — Claude Code が 17 個の MCP ツールを通じて、ネイティブにテストを作成、実行、デバッグします。「チェックアウトのフローをテストして」と頼むだけで、JSON を作成して実行し、結果を報告します。
🐛 課題からテストまでのパイプライン — GitHub または GitLab の課題 URL を貼り付けると、ランナーが課題を取得し、E2E テストを生成して実行し、バグを確認 または 再現できません と報告します。
👁️ 視覚的な検証 — ページに期待する見た目を平易な言葉で説明します。AI がスクリーンショットを撮影し、その説明に照らして合否を判定します。ピクセル差分の設定は不要です。
🧠 学習システム — 実行ごとのテストの安定性を追跡します。不安定なテスト、安定しないセレクター、遅い API、エラーパターンを検出し、実行可能な分析情報を提示します。
⚡ 並列実行 — 共有ブラウザープール(browserless、raw CDP、Lightpanda、Obscura、または Steel)に対して N 個のテストを同時に実行します。状態を共有するテスト向けに、シリアルモードも利用できます。
🎯 差し替え可能なブラウザードライバー — 各テストに合ったエンジンを選べます。browserless 経由の実際の Chrome、または高速で軽量な実行向けの Lightpanda や Obscura、マネージドセッション向けの Steel を利用できます。テストごとに driver を設定するか、--driver で実行全体を上書きできます。
📊 リアルタイムダッシュボード — 実行状況のライブ表示、合格率チャート付きの実行履歴、ハッシュ検索に対応したスクリーンショットギャラリー、展開可能なネットワークリクエストログを利用できます。
🔁 スマートな再試行 — テスト単位およびアクション単位で、遅延を設定して再試行できます。不安定なテストは自動で検出され、フラグが付けられます。
📦 再利用可能なモジュール — 共通のフロー(ログイン、ナビゲーション、セットアップ)をパラメーター化したモジュールとして切り出し、$use で参照できます。
🏗️ CI 対応 — JUnit XML 出力、失敗時の終了コード 1、自動取得されるエラーのスクリーンショットに対応しています。GitHub Actions のサンプルもそのまま使えます。
🌐 マルチプロジェクト — 1 つのダッシュボードに、すべてのプロジェクトのテスト結果を集約します。1 つの Chrome プールですべてのプロジェクトに対応します。
🐳 ポータブル — Chrome は Docker で実行し、テストはリポジトリ内の JSON ファイルで管理します。Node.js と Docker があれば、どのマシンでも動作します。
✍️ テストの作成
テストの作成に必要なすべての情報を紹介します。ファイル形式、アクションの全一覧、再試行、状態の分離、再利用について、必要な項目を展開してください。
テスト形式とファイル構成
e2e/tests/ 内の各 .json ファイルには、テストの配列が含まれます。各テストには name と、順番に実行される actions があります。
[
{
"name": "homepage-loads",
"actions": [
{ "type": "goto", "value": "/" },
{ "type": "assert_visible", "selector": "body" },
{ "type": "assert_url", "value": "/" },
{ "type": "screenshot", "value": "homepage.png" }
]
}
]
順序を指定するために、スイートファイルに数値の接頭辞を付けることができます(01-auth.json、02-dashboard.json)。--suite フラグは接頭辞の有無を問わず一致するため、--suite auth で 01-auth.json が見つかります。
アクション一覧 — ナビゲーション、入力、操作
| アクション | フィールド | 説明 | |--------|--------|-------------| | `goto` | `value` | URL に移動します(`baseUrl` からの相対 URL または絶対 URL) | | `click` | `selector` または `text` | CSS セレクターまたは表示されているテキストでクリックします。テキストモードでは `scope: "dialog"`、`visible: true`、`last: true` も指定できます | | `type` / `fill` | `selector`、`value` | フィールドをクリアしてテキストを入力します | | `wait` | `selector`、`text`、`gone`、または `value`(ms) | 要素/テキストが表示されるまで待機します。`gone` の場合は要素(スピナー/ダイアログ)が消えるまで待機し、`value` の場合は指定した時間だけ待機します。固定の `value` による待機より、条件による待機を優先してください | | `screenshot` | `value`(ファイル名) | スクリーンショットを撮影します | | `select` | `selector`、`value` | ドロップダウンのオプションを選択します | | `clear` | `selector` | 入力フィールドをクリアします | | `press` | `value` | キーボードキー(`Enter`、`Tab` など)を押します | | `scroll` | `selector` または `value`(px) | 要素まで、または指定したピクセル数だけスクロールします | | `hover` | `selector` | 要素にカーソルを合わせます | | `evaluate` | `value` | ブラウザーコンテキストで JavaScript を実行します | | `navigate` | `value` | ブラウザーを操作します(`back`、`forward`、`reload`) | | `clear_cookies` | — | 現在のページのすべての Cookie をクリアします | | `wait_network_idle` | `value`(アイドル時間(ms)、デフォルトは 500)、`timeout`(省略可) | ネットワークが `value` ms の間アイドル状態になるまで待機します。バックグラウンドリクエストを発生させるアクションの後に便利です | | `set_storage` | `value`(`"key=val"`)、`selector: "session"`(省略可) | `localStorage` のキーを設定します(`selector: "session"` を指定すると `sessionStorage` に設定します) | | `gql` | `value`(クエリ)、`text`(変数 JSON、省略可)、`selector`(アサーション、省略可) | ページ内の `fetch` を介して GraphQL クエリ/ミューテーションを実行し、`localStorage` から認証トークンを読み取ります。GraphQL エラーがある場合は失敗します。`selector` はレスポンス `r` に対して評価される JS 式です(例:`"r.data.users.length > 0"`)。後続の `evaluate` ステップで使用できるよう、`window.__e2eGql` をインストールします |
テキストでクリック — click で selector の代わりに text を使うと、一般的なインタラクティブ要素やコンテンツ要素を横断して検索します。
button, a, [role="button"], [role="tab"], [role="menuitem"], [role="option"],
[role="listitem"], div[class*="cursor"], span, li, td, th, label, p, h1-h6
{ "type": "click", "text": "Sign In" }
アサーション — テキスト、要素、URL、件数、ネットワークを検証します
| アクション | フィールド | 説明 | |--------|--------|-------------| | `assert_text` | `text` | ページ内の任意の場所にテキストが存在することをアサートします(部分一致) | | `assert_no_text` | `text` | ページ内の任意の場所にテキストが表示されないことをアサートします。`assert_text` の逆です | | `assert_text_in` | `selector`、`text`、省略可能な `value: "exact"` | 範囲を指定したコンテナー内のテキストをアサートします。デフォルトでは `text` は大文字と小文字を区別しない正規表現です。`value: "exact"` を指定すると、大文字と小文字を区別する部分一致に切り替わります | | `assert_element_text` | `selector`、`text`、省略可能な `value: "exact"` | 要素のテキストに期待するテキストが含まれる(または完全に一致する)ことをアサートします | | `assert_url` | `value` | 現在の URL パスまたは完全な URL をアサートします。パス(`/dashboard`)は pathname のみと比較されます | | `assert_visible` | `selector` | 要素が存在し、表示されていることをアサートします | | `assert_not_visible` | `selector` | 要素が非表示、または存在しないことをアサートします | | `assert_attribute` | `selector`、`value` | 属性を確認します。値には `"type=email"`、存在確認には `"disabled"` を指定します | | `assert_class` | `selector`、`value` | 要素が CSS クラスを持つことをアサートします | | `assert_input_value` | `selector`、`value` | input/select/textarea の `.value` にテキストが含まれることをアサートします | | `assert_matches` | `selector`、`value`(正規表現) | 要素のテキストが正規表現パターンに一致することをアサートします | | `assert_count` | `selector`、`value` | 要素数をアサートします。完全一致(`"5"`)、または演算子(`">3"`、`">=1"`、`"<10"`)を指定できます | | `assert_no_network_errors` | — | ネットワークリクエストが失敗した場合に失敗します(例:`ERR_CONNECTION_REFUSED`) | | `assert_storage` | `value`(`"key"` または `"key=expected"`)、省略可能な `selector: "session"` | `localStorage`/`sessionStorage` のキーが存在すること、または特定の値を持つことをアサートします | | `assert_visual` | `value`(ゴールデン画像)、省略可能な `selector`、`text`(最大差分、例:`"0.02"`)、`fullPage`、`maskRegions`、`threshold` | ビジュアルリグレッション:スクリーンショットをゴールデン参照画像と比較します。初回実行時にゴールデン画像が保存されます。以降の実行では、しきい値(デフォルトは 2%)を超えるピクセル数に差異があると失敗し、差分画像が書き出されます | | `get_text` | `selector` | 要素のテキストを抽出します(アサーションではないため、失敗しません)。結果:`{ value: "..." }` |
フレームワーク対応アクション — evaluate の定型コードなしで React/MUI を操作
これらのアクションは、通常は冗長な evaluate の定型コードが必要となる React/MUI アプリの一般的なパターンに対応します。
| アクション | フィールド | 説明 |
|---|---|---|
type_react | selector、value、省略可能な blur、waitAfter | ネイティブの値セッターを使って、React が制御する入力欄に入力します。input と change イベントをディスパッチし、React の状態が正しく更新されるようにします。blur: true はフォーカスが外れたときに値を確定します。waitAfter: "<ms>" は入力後に待機します(デバウンスされたオートコンプリート用)。 |
click_regex | text(正規表現)、省略可能な selector、省略可能な value: "last" | テキストコンテンツが正規表現に一致する要素をクリックします(大文字と小文字は区別しません)。デフォルトでは最初に一致した要素をクリックします。最後に一致した要素をクリックするには value: "last" を使います。 |
click_option | text | テキストを指定して [role="option"] 要素をクリックします。オートコンプリートやセレクトのドロップダウンでよく使われます。 |
select_combobox | text、省略可能な selector、filter、openWait/filterWait/waitAfter | MUI の Autocomplete/Select を開き、必要に応じて filter を入力した後、text に一致するオプションをクリックします。[role="option"]、.MuiAutocomplete-option、li.MuiMenuItem-root の順にフォールバックします。 |
focus_autocomplete | text(ラベルテキスト) | ラベルテキストを指定して、オートコンプリートの入力欄にフォーカスします。MUI と汎用の [role="combobox"] に対応しています。 |
click_chip | text | テキストを指定してチップ/タグ要素をクリックします。[class*="Chip"]、[class*="chip"]、[data-chip] を検索します。 |
click_icon | value(アイコン ID)、省略可能な selector(範囲) | data-testid/data-icon/aria-label/クラスの一部、または SVG の <title> でアイコンを指定してクリックします。MUI、FontAwesome、Heroicons などに対応しています。最も近いクリック可能な祖先要素(ボタン、リンク、タブ)をクリックします。 |
click_menu_item | text、省略可能な selector(範囲) | [role="menuitem"]、.dropdown-item、.menu-item、MUI の MenuItem から、テキストを指定してメニュー項目をクリックします。 |
click_in_context | text(コンテナのテキスト)、selector(子要素) | text に一致する最小のコンテナ内にある子要素をクリックします。たとえば、特定のカード/行にある削除ボタンをクリックできます。 |
// Before: 5 lines of evaluate boilerplate
{ "type": "evaluate", "value": "const input = document.querySelector('#search'); const nativeSet = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, 'value').set; nativeSet.call(input, 'term'); input.dispatchEvent(new Event('input', {bubbles: true})); input.dispatchEvent(new Event('change', {bubbles: true}));" }
// After: 1 action
{ "type": "type_react", "selector": "#search", "value": "term" }
複数タブのアクション — ポップアップ、OAuth ウィンドウ、タブ間のフロー
| アクション | フィールド | 説明 |
|---|---|---|
open_tab | value(URL)、省略可能な text(ラベル) | 新しいタブを開き、URL に移動します(baseUrl からの相対 URL または絶対 URL)。ラベルのデフォルトは tab-<n> です。 |
switch_tab | value | ラベル、数値インデックス、またはタイトル/URL との一致(正規表現または部分文字列)で、アクティブなタブを切り替えます。"default" を指定すると元のタブに戻ります。 |
wait_for_tab | 省略可能な text(ラベル)、timeout | アプリが開いた新しいタブ/ポップアップ(window.open、target="_blank")を待機し、そのタブをアクティブにします。 |
assert_tab_count | value | 開いているタブの数を検証します。正確な数("2")または演算子(">=2")を指定できます。 |
close_tab | 省略可能な value(ラベル) | 現在のタブ(または名前を指定したタブ)を閉じ、最後に残ったタブに切り替えます。 |
以降のすべてのアクションは、アクティブなタブで実行されます。
{ "type": "click", "text": "Open report" }
{ "type": "wait_for_tab", "text": "report" }
{ "type": "assert_text", "text": "Quarterly results" }
{ "type": "close_tab" }
再試行と不安定なテストの検出
テスト単位の再試行 — テスト全体を失敗時に再試行します。設定ファイルで全体に設定するか、テストごとに設定します。
{ "name": "flaky-test", "retries": 3, "timeout": 15000, "actions": [...] }
再試行後に成功したテストは、レポートと学習システムで不安定としてフラグ付けされます。
アクション単位の再試行 — テスト全体を再実行せずに、単一のアクションを再試行します。タイミングに左右されるクリックや待機に便利です。
{ "type": "click", "selector": "#dynamic-btn", "retries": 3 }
{ "type": "wait", "selector": ".lazy-loaded", "retries": 2 }
全体に設定するには、設定ファイルの actionRetries、CLI の --action-retries <n>、または環境変数の ACTION_RETRIES を使います。再試行間の遅延は actionRetryDelay で設定します(デフォルトは 500ms)。
シリアルテスト — 状態を共有するテスト向け
状態を共有するテスト(たとえば、同じレコードを変更する 2 つのテスト)は、並列実行時に競合する可能性があります。シリアルとして指定します。
{ "name": "create-patient", "serial": true, "actions": [...] }
{ "name": "verify-patient-list", "serial": true, "actions": [...] }
シリアルテストは、すべての並列テストの完了後に一度に 1 つずつ実行されます。これにより、独立したテストの実行を遅くすることなく、干渉を防げます。
認証が必要なアプリのテスト
最も簡単な方法は、実際のユーザーと同じように UI からログインすることです。
{
"hooks": {
"beforeEach": [
{ "type": "goto", "value": "/login" },
{ "type": "type", "selector": "#email", "value": "[email protected]" },
{ "type": "type", "selector": "#password", "value": "test-password" },
{ "type": "click", "text": "Sign In" },
{ "type": "wait", "selector": ".dashboard" }
]
},
"tests": [...]
}
JWT を使用する SPA の場合は、トークンを直接注入してログインフォームをスキップします。
{ "type": "set_storage", "value": "accessToken=eyJhbGciOiJIUzI1NiIs..." }
または、設定ファイルでグローバルに設定します。
// e2e.config.js
export default {
authToken: 'eyJhbGciOiJIUzI1NiIs...',
authStorageKey: 'accessToken',
};
各テストは新しいブラウザーコンテキストで実行されるため、テスト間で認証状態は自動的にクリーンになります。
その他の方法: Cookie ベースの認証、HTTP ヘッダーの注入、OAuth/SSO のバイパス、再利用可能な認証モジュール、ロールベースのテストについては、docs/authentication.md をご覧ください。
再利用可能なモジュール — $use で共通のフローを抽出
共通のフローをパラメーター化されたモジュールに抽出します。
// e2e/modules/login.json
{
"$module": "login",
"description": "Log in via the UI login form",
"params": {
"email": { "required": true, "description": "User email" },
"password": { "required": true, "description": "User password" }
},
"actions": [
{ "type": "goto", "value": "/login" },
{ "type": "type", "selector": "#email", "value": "{{email}}" },
{ "type": "type", "selector": "#password", "value": "{{password}}" },
{ "type": "click", "text": "Sign In" },
{ "type": "wait", "value": "2000" }
]
}
テストで使用します。
{
"name": "dashboard-loads",
"actions": [
{ "$use": "login", "params": { "email": "[email protected]", "password": "secret" } },
{ "type": "assert_text", "text": "Dashboard" }
]
}
モジュールは、パラメーターの検証(必須パラメーターがない場合は即座に失敗)、条件付きブロック({{#param}}...{{/param}})、ネストした合成、循環参照の検出をサポートしています。
フック — beforeAll / beforeEach / afterEach / afterAll
ライフサイクルの各タイミングでアクションを実行します。設定ファイルまたは各スイートで定義できます。
{
"hooks": {
"beforeAll": [{ "type": "goto", "value": "/setup" }],
"beforeEach": [{ "type": "goto", "value": "/" }],
"afterEach": [{ "type": "screenshot", "value": "after.png" }],
"afterAll": []
},
"tests": [...]
}
重要:
beforeAllは別のブラウザーページで実行され、テスト開始前にそのページは閉じられます。テストで必要な状態(Cookie、localStorage、認証トークン)にはbeforeEachを使用してください。
除外パターン — --all の実行から下書きを除外
探索用または下書きのテストを --all の実行から除外します。
// e2e.config.js
export default {
exclude: ['explore-*', 'debug-*', 'draft-*'],
};
個別のスイート実行(--suite)は、除外パターンの影響を受けません。
🤖 AI 連携
AI エージェントがテストを作成、実行、検証してくれるのが、このツールの目的です。
Claude Code — プラグインのインストールと MCP のみのインストール
claude plugin marketplace add fastslack/mtw-e2e-runner
claude plugin install e2e-runner@matware
Claude Code に 17 個の MCP ツール、ワークフロースキル、4 つのスラッシュコマンド(/e2e-runner:run、/e2e-runner:create-test、/e2e-runner:verify-issue、/e2e-runner:capture)、3 つの特化型エージェント(test-analyzer、test-creator、test-improver)が追加されます。
MCP のみのインストール(ツールのみ。スキル、コマンド、エージェントは含まれません):
claude mcp add --transport stdio --scope user e2e-runner \
-- npx -y -p @matware/e2e-runner e2e-runner-mcp
OpenCode
cp node_modules/@matware/e2e-runner/opencode.json ./
mkdir -p .opencode && cp -r node_modules/@matware/e2e-runner/.opencode/* .opencode/
詳細は OPENCODE.md を参照してください。
17 個の MCP ツール
| ツール | 説明 |
|---|---|
e2e_run | テストを実行します(すべて、スイート別、またはファイル別) |
e2e_list | 利用可能なテストスイートを一覧表示します |
e2e_create_test | 新しいテスト JSON ファイルを作成します |
e2e_create_module | 再利用可能なモジュールを作成します |
e2e_pool_status | Chrome プールの状態を確認します |
e2e_app_pool_status | アプリ環境プール(フォーク、ポート、ドライバー)を調べます |
e2e_screenshot | ハッシュを指定してスクリーンショットを取得します |
e2e_capture | 任意の URL のスクリーンショットを撮影します |
e2e_analyze | ページ構造(インタラクティブ要素、フォーム、見出し)を抽出し、テストのひな形を出力します |
e2e_dashboard_start | ウェブダッシュボードを起動します |
e2e_dashboard_stop | ウェブダッシュボードを停止します |
e2e_dashboard_restart | ダッシュボードを再起動します(新しいプロジェクトディレクトリ/ポートを使用し、古いセッションを消去します) |
e2e_issue | イシューを取得してテストを生成します |
e2e_network_logs | 実行時のネットワークログを検索します |
e2e_learnings | 安定性に関する分析情報を検索します |
e2e_vars | SQLite を利用した {{var.KEY}} プロジェクト変数を管理します |
e2e_neo4j | Neo4j ナレッジグラフを管理します |
プールの起動/停止は CLI 専用です。MCP では公開されていません。
ビジュアル検証 — ページを説明すると、AI が判定します
ページの見た目を説明すると、AI がスクリーンショットから合否を判定します:
{
"name": "dashboard-loads",
"expect": "Patient list with at least 3 rows, no error messages, sidebar with navigation links",
"actions": [
{ "type": "goto", "value": "/dashboard" },
{ "type": "wait", "selector": ".patient-list" }
]
}
テストアクションの完了後、ランナーが検証用スクリーンショットを自動で撮影します。MCP の応答にはスクリーンショットのハッシュが含まれ、Claude Code がこれを取得して、expect の説明と照らし合わせて視覚的に検証します。API キーは不要です。
イシューからテストを作成 — バグ報告を実行可能なテストに変換します
GitHub と GitLab のイシューを実行可能な E2E テストに変換します。イシューの URL を貼り付けるだけで、実行可能なテストを自動で作成できます。
仕組み:
- 取得 —
ghまたはglabCLI を使って、イシューの詳細(タイトル、本文、ラベル)を取得します - 生成 — AI がイシューの説明に基づいて JSON テストアクションを作成します
- 実行 — 必要に応じてテストをすぐに実行し、バグが再現するかどうかを検証します
# Fetch and display
e2e-runner issue https://github.com/owner/repo/issues/42
# Generate a test file via Claude API
e2e-runner issue https://github.com/owner/repo/issues/42 --generate
# Generate + run + report
e2e-runner issue https://github.com/owner/repo/issues/42 --verify
# -> "BUG CONFIRMED" or "NOT REPRODUCIBLE"
Claude Code では、次のように依頼するだけです:
「イシュー #42 を取得して、E2E テストを作成してください」
バグ検証の仕組み: 生成されたテストは正しい動作を検証します。テストが失敗した場合は、バグが確認されたことを意味します。すべてのテストに合格した場合は、再現できなかったことを意味します。
認証: GitHub には gh CLI、GitLab には glab CLI が必要です。セルフホスト型 GitLab にも対応しています。
📊 ダッシュボードと分析情報
e2e-runner dashboard # Start on default port 8484
e2e-runner dashboard --port 9090 # Custom port
ウェブダッシュボードの概要 — ライブ表示、履歴、ギャラリー、プールの状態
ライブ実行 — ステップごとの進捗、所要時間、稼働中のワーカー数を確認しながら、テストをリアルタイムで監視できます。
テストスイート — プロジェクト全体のすべてのスイートを閲覧できます。ワンクリックで単一のスイート、またはすべてのテストを実行できます。
実行詳細 — PASS/FAIL バッジ、コピー可能なハッシュ(ss:77c28b5a)付きのスクリーンショットサムネイル、整形されたコンソールエラー、ネットワークリクエストログを表示します。
スクリーンショットギャラリー — ハッシュ検索で、キャプチャしたすべてのスクリーンショット(アクション、エラー、検証時のキャプチャ)を閲覧できます。
プールのステータス — Chrome プールの稼働状況(利用可能なスロット、実行中のセッション、メモリ負荷)を確認できます。
学習システム — 不安定なテスト、不安定なセレクター、低速な API
ランナーはテストを実行するたびに学習し、時間の経過とともにテストスイートに関するナレッジを構築します。e2e_learnings MCP ツールでインサイトを照会できます。
| クエリ | 返される内容 |
|---|---|
summary | 合格率、不安定なテスト、不安定なセレクター、API の問題を含む、ヘルス状態の全体概要 |
flaky | 再試行後にのみ合格するテスト |
selectors | 失敗率の高い CSS セレクター |
pages | コンソールエラー、ネットワーク障害、読み込み時間の問題があるページ |
apis | エラー率とレイテンシを含む API エンドポイント(UUID、ハッシュ、ID は自動的に正規化されます) |
errors | 発生頻度の高いエラーパターン(分類済み) |
trends | 時間経過に伴う合格率(データがすべて同じ日の場合は、時間単位に自動で切り替わります) |
test:<name> | 特定のテストの詳細な実行履歴 |
page:<path> | 特定のページの詳細な実行履歴 |
selector:<value> | 特定のセレクターの詳細な実行履歴 |
ストレージとエクスポート:
- SQLite(
~/.e2e-runner/dashboard.db)— デフォルト。セットアップ不要 - Neo4j ナレッジグラフ — 任意。関係に基づく分析向け。
e2e_neo4jMCP ツールまたはdocker composeで管理できます - Markdown レポート(
e2e/learnings.md)— 各実行後に自動生成
テストのナレーション: 各テストの実行時に、発生した内容を手順ごとに説明する、人が読みやすい形式のナラティブを生成します。CLI 出力とダッシュボードで確認できます。
ネットワークエラーの処理 — アサーション、グローバルフラグ、詳細なログ
明示的なアサーション — 重要なページの読み込み後に assert_no_network_errors を配置します。
{ "type": "goto", "value": "/dashboard" },
{ "type": "wait", "selector": ".loaded" },
{ "type": "assert_no_network_errors" }
グローバルフラグ — failOnNetworkError: true を設定すると、ネットワークエラーが発生したテストは自動的に失敗します。
e2e-runner run --all --fail-on-network-error
無効の場合(デフォルト)、ランナーはネットワークエラーを収集して報告します。テストが合格してもネットワークエラーがある場合、MCP のレスポンスに警告が含まれます。
詳細なネットワークログ — すべての XHR/fetch リクエストをキャプチャし、URL、メソッド、ステータス、所要時間、リクエスト/レスポンスヘッダー、レスポンス本文(50KB で切り詰め)を記録します。ダッシュボードで、リクエストの詳細行を展開して確認できます。
MCP の詳細確認フロー:
1. e2e_run → compact networkSummary + runDbId
2. e2e_network_logs(runDbId) → all requests (url, method, status, duration)
3. e2e_network_logs(runDbId, errorsOnly: true) → only failed requests
4. e2e_network_logs(runDbId, includeHeaders: true) → with headers
5. e2e_network_logs(runDbId, includeBodies: true) → full request/response bodies
キャプチャしたリクエスト数にかかわらず、e2e_run のレスポンスはコンパクト(約 5KB)に保たれます。返された runDbId を e2e_network_logs で使用すると、必要に応じて詳細を確認できます。
スクリーンショットのキャプチャ — 任意の URL をオンデマンドで撮影
テストスイートを用意せずに、任意の URL のスクリーンショットをオンデマンドで撮影できます。
e2e-runner capture https://example.com
e2e-runner capture https://example.com --full-page --selector ".loaded" --delay 2000
MCP 経由では、e2e_capture ツールで authToken と authStorageKey を指定して、認証が必要なページに対応できます。ページに移動する前に、トークンを localStorage に注入します。
🌐 ブラウザードライバー
ランナーは、複数のブラウザーエンジンと、それぞれに対応するドライバーを介して通信できます。デフォルトは auto です。各プールの URL を調べ、プールごとに適切なドライバーを選びます。
| ドライバー | エンジン | 検出プローブ | 使用する場面 |
|---|---|---|---|
browserless | browserless を介した実際の Chromium | /pressure が JSON を返す | デフォルト。プロダクション品質の JS 実行、スクリーンキャスト、完全な Chrome の動作 |
cdp | 汎用の CDP 互換(raw Chrome など) | /json/version にアクセス可能 | 他のいずれにも該当しない CDP サーバーのフォールバック |
lightpanda | Lightpanda(Zig) | /json/version の Browser=lightpanda | ヘッドレス Chrome より約 9 倍高速、メモリ使用量は約 16 分の 1。大量のスクレイピング形式のテストに最適 |
obscura | Obscura(Rust + V8) | /json/version の Browser=obscura | RAM 使用量は約 30 MB。組み込みの検出回避(--stealth)機能があり、Puppeteer を介して実際の Chrome に近い状態を維持 |
steel | Steel Browser | /v1/sessions が JSON を返す | セッションライフサイクルを管理し、オーケストレーション用の REST API を提供 |
テストごとにドライバーを選択/実行全体でドライバーを固定
{
"tests": [
{
"name": "checkout flow (heavy JS, real Chrome)",
"driver": "browserless",
"actions": [...]
},
{
"name": "scrape product page (lightweight)",
"driver": "obscura",
"fallbackDriver": "cdp",
"actions": [...]
}
]
}
driver は省略可能です。設定すると、検出されたドライバーが一致するプールのみが候補になります。fallbackDriver は明示的なオプトインです。指定しない場合、対象ドライバーが見つからないと、明確なメッセージとともにテストが失敗します。プールの混雑を理由にフォールバックすることはありません。ランナーはフィルター後の候補内で待機します。
実行全体でドライバーを固定します(CLI の設定はテストごとの設定より優先されます。A/B ベンチマークに便利です)。
e2e-runner run --all --driver obscura
e2e-runner run --all --driver obscura --fallback-driver cdp
各ドライバーをローカルで実行する
# browserless (default) — managed by `pool start`
e2e-runner pool start
# Lightpanda — pool start uses templates/docker-compose-lightpanda.yml
e2e-runner pool start # with poolDriver: 'lightpanda' in config
# Obscura — install the binary and run it yourself
curl -LO https://github.com/h4ckf0r0day/obscura/releases/latest/download/obscura-x86_64-linux.tar.gz
tar xzf obscura-x86_64-linux.tar.gz
./obscura serve --port 9222 --stealth
# then point the runner at it: poolUrls: ['http://localhost:9222'], poolDriver: 'obscura'
⚙️ CLI、設定、CI
CLI コマンド
# Run tests
e2e-runner run --all # All suites
e2e-runner run --suite auth # Single suite
e2e-runner run --tests path/to.json # Specific file
e2e-runner run --inline '<json>' # Inline JSON
# Pool management (CLI only, not MCP)
e2e-runner pool start # Start Chrome container
e2e-runner pool stop # Stop Chrome container
e2e-runner pool status # Check pool health
# Issue-to-test
e2e-runner issue <url> # Fetch issue
e2e-runner issue <url> --generate # Generate test via AI
e2e-runner issue <url> --verify # Generate + run + report
# Dashboard
e2e-runner dashboard # Start web dashboard
# Other
e2e-runner list # List available suites
e2e-runner capture <url> # On-demand screenshot
e2e-runner init # Scaffold project
CLI オプション
| フラグ | デフォルト | 説明 |
|---|---|---|
--base-url <url> | http://host.docker.internal:3000 | アプリケーションのベース URL |
--pool-url <ws> | ws://localhost:3333 | Chrome プールの WebSocket URL |
--concurrency <n> | 3 | 並列テストワーカー数 |
--retries <n> | 0 | 失敗したテストを N 回再試行 |
--action-retries <n> | 0 | 失敗したアクションを N 回再試行 |
--test-timeout <ms> | 60000 | テストごとのタイムアウト |
--timeout <ms> | 10000 | デフォルトのアクションタイムアウト |
--output <format> | json | レポート形式:json、junit、both |
--env <name> | default | 環境プロファイル |
--fail-on-network-error | false | ネットワークエラーが発生したテストを失敗させる |
--project-name <name> | dir name | プロジェクトの表示名 |
--driver <name> | (テストごと) | 実行全体でプールのドライバーを固定:browserless、cdp、lightpanda、obscura、steel |
--fallback-driver <name> | なし | --driver を指定したプールに接続できない場合の明示的なフォールバック |
設定 — e2e.config.js と優先順位
プロジェクトのルートに e2e.config.js を作成します。
export default {
baseUrl: 'http://host.docker.internal:3000',
concurrency: 4,
retries: 2,
actionRetries: 1,
testTimeout: 30000,
outputFormat: 'both',
failOnNetworkError: true,
exclude: ['explore-*', 'debug-*'],
hooks: {
beforeEach: [{ type: 'goto', value: '/' }],
},
environments: {
staging: { baseUrl: 'https://staging.example.com' },
production: { baseUrl: 'https://example.com', concurrency: 5 },
},
};
設定の優先順位(上位が優先されます):
- CLI フラグ
- 環境変数
- 設定ファイル(
e2e.config.jsまたはe2e.config.json) - デフォルト値
--env <name> を設定すると、一致するプロファイルがすべての設定より優先されます。
CI/CD — JUnit XML と GitHub Actions
e2e-runner run --all --output junit
jobs:
e2e:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
- run: npm ci
- run: npx e2e-runner pool start
- run: npx e2e-runner run --all --output junit
- uses: mikepenz/action-junit-report@v4
if: always()
with:
report_paths: e2e/screenshots/junit.xml
プログラムから利用する API
import { createRunner } from '@matware/e2e-runner';
const runner = await createRunner({ baseUrl: 'http://localhost:3000' });
const report = await runner.runAll();
const report = await runner.runSuite('auth');
const report = await runner.runFile('e2e/tests/login.json');
const report = await runner.runTests([
{ name: 'quick-check', actions: [{ type: 'goto', value: '/' }] },
]);
要件
- Node.js >= 20
- Docker — オプション 3(並列 Chrome プール)でのみ必要です。オプション 1 と 2 では不要です。
ライセンス
Copyright 2026 Matias Aguirre (fastslack) — Matware
Apache License, Version 2.0 に基づいてライセンスされています。詳細については、LICENSE を参照してください。
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。