😺

Playwright の Trace / Video / Screenshot を「アプリ内で開く」設計の話

に公開

落ちたテストを開く瞬間、何回ファイラを行き来していますか

Playwright で E2E テストを回していると、失敗時の調査資産は自然と 3 種類に集約されます。

  • Tracetrace.zipnpx playwright show-trace で開く、DOM スナップショット付きの実行記録
  • Video*.webm。実行中のブラウザ画面を録画したもの
  • Screenshot*.png。失敗時点のキャプチャ

どれも単体では強力なんですが、運用に乗せると地味に効いてくるのが 「散らばる」 という問題です。test-results/ の下に実行ごとのフォルダが切られて、その中に動画と trace が落ちている。落ちたテストを調べるたびに、ファイラを開いて、目当てのフォルダを探して、trace.zipshow-trace に渡して、別ウィンドウで動画を再生して……というのをやることになる。

E2E テストは「落ちたときが本番」なので、この 調査動線の段差 はそのままチーム全体の調査時間に効いてきます。

この記事では、Playwright の artifacts を Electron アプリ内から直接開けるようにする──という設計判断について書きます。

設計上の論点:なぜ「アプリ内で開く」のか

最初に検討すべきなのは、そもそもアプリ内ビューアは要るのか という点です。

選択肢としてはざっくり 3 つあります。

方式 メリット デメリット
OS デフォルトに任せる(ファイラ / 関連付け) 実装ゼロ 動線が分断、trace は Playwright CLI が必要
Web の Trace Viewer に飛ばす ホスティングだけで済む オフライン / 社内ネットワーク前提だと厳しい
アプリ内ビューア テスト一覧 → 結果 → 証跡が一動線で繋がる 実装コストがかかる

ローカル完結のデスクトップアプリで、なおかつ QA メンバーが日常的に触る前提なら、3 つ目の "アプリ内で開く" を選ぶ価値があります。テストの一覧画面から「失敗したテストをクリック → そのまま動画を見る → trace で DOM を追う」が 1 ウィンドウで完結する、という体験はそれだけで調査時間を短くします。

アプリ内ビューアの責務分解

ビューアと一口に言っても、扱うものが 3 種類あるので、責務をきちんと分けて考えると見通しがよくなります。

1. Screenshot

一番素直。PNG をそのまま <img> で表示すれば終わり……に見えますが、設計上は 「アプリのレンダラからローカルファイルをどう読むか」 という Electron 固有の判断が挟まります。file:// を直接食わせるか、Main プロセスで読んで Data URL にしてレンダラに渡すか、という選択。セキュリティ設定と相談しながら決めるところです。

2. Video (WebM)

ブラウザ標準の <video> で再生できるので、表示自体は素直です。ここで考えるべきは 「シーク・倍速・コマ送り」を入れるかどうか。E2E の調査では「落ちる直前を何度も見たい」というニーズがあるので、最低限シークバーと再生速度の切り替えはあると効きます。

3. Trace (ZIP)

ここが一番重い。trace.zip の中には DOM スナップショット、ネットワーク、コンソールログなどが入っていて、Playwright 公式の Trace Viewer は単独で 1 アプリと言えるくらいの規模があります。

設計選択は大きく 2 つ。

  • A. Playwright 公式 Trace Viewer に丸投げする — 子プロセスとして起動し、別ウィンドウで開く。実装が薄く、Playwright のアップデートに自動追従できる
  • B. アプリ内に自前で組み込む — 中身を解凍してレンダラ側でレンダリングする。一動線になるが、Playwright のアップデートを追い続けるコストが乗る

「公式の Trace Viewer は強力だが、UI 統合度を取るか追従コストを取るか」というトレードオフです。まず A で出して、ニーズが固まってから B に踏み込む のが現実的な順序だと考えています。

アーキテクチャ:Renderer と Main の境界

artifacts は基本的に ローカルファイル なので、扱いはどうしても Main プロセス側(Electron)に寄ります。一方、表示は Renderer(React)側。この境界を意識せずに作ると、fs を触りたくなった瞬間に詰まる、という事故が起こります。

Renderer は "パス" を直接持たせず、Main から渡される識別子で取り回す こと。テスト実行 ID と artifact 種別さえあれば、Main 側で実体パスを解決できる、という形にしておくとセキュリティ的にも保守的にも楽になります。

履歴と紐づける:単発のビューアに留めない

artifact ビューアを単発の機能として作ると、「動画は見られるけど、いつのどのテストの動画かわからない」という状態になりがちです。

設計として効いてくるのは、実行履歴 (history) と artifacts を 1 対 1 で紐づけて保持する こと。TestRunResulthistory の各要素として時系列に積まれていて、それぞれが自分の artifacts を持っている、という構造にしておくと、「3 回前の失敗のときの動画を見たい」が自然にできるようになります。

副次的な効果として、履歴保持数の設定 が artifact のディスク使用量にも効いてくるので、maxHistoryLength のような設定値が単なる UI 都合ではなく ストレージ管理の意味も持つ ことになります。villatech ではここを AppSettings.maxHistoryLength(デフォルト 10)と saveArtifacts(trace / video / screenshot それぞれ on/off)で持っていて、運用側で「動画はディスク食うから切る」みたいな判断ができるようになっています。

まとめ

E2E テストの artifact 表示は、技術的には「PNG を出す・WebM を再生する・ZIP を扱う」だけなので地味です。ただ、チームで Playwright を回し続けるとき、この調査動線の差は累積で効いてくる 領域でもあります。

設計の論点を整理すると:

  • アプリ内で開く意味 はテスト → 結果 → 証跡を 1 動線にすることにある
  • Trace の扱い は公式 Viewer 起動 / 自前組み込みのトレードオフ。まずは前者
  • Renderer / Main の境界 を意識し、パスではなく識別子で artifact を取り回す
  • 履歴と artifact を 1 対 1 で紐づけ、保持数を運用側で制御できるようにする

このあたりの考え方を実際にデスクトップアプリに落とし込んだのが villatech(ビラテク) という E2E テスト自動化ツールで、Playwright を「GUI から回す・履歴で追う・証跡をその場で開く」を一つのアプリにまとめています。Playwright 資産はあるけど運用側で詰まっている、という方は触ってみてもらえると。

もし AI 開発やテスト自動化、QA 体制について課題があればお気軽にご相談ください。

株式会社nascimento
https://nascimento.co.jp/

Discussion