Playwrightのテストが重い原因を特定!パフォーマンスを劇的に向上させる技法

Playwrightの重いテストを分析し、設定とコード改善で高速化する開発イメージ フロントエンド

PlaywrightでE2Eテストを書き始めた直後は快適でも、テストケースが増えるにつれて実行時間が急に重くなることがあります。
CIの待ち時間が長くなり、手元での確認にも集中力を削がれる。
失敗の原因調査よりも、まず「遅いこと」自体が開発体験を悪化させる場面も少なくありません。
では、Playwrightのテストはなぜ重くなるのでしょうか。
単純にケース数が増えたから、という説明だけでは不十分です。
実際には、ブラウザ起動の回数、不要な待機、テストデータの初期化、並列実行の設計、セレクタの取り方、認証処理の繰り返しなど、複数の要因が絡み合って全体のパフォーマンスを押し下げています。

この記事では、Playwrightのテストが重くなる典型的な原因を分解し、どこを計測し、どこを疑い、どの順序で改善すべきかを整理していきます。
感覚的にチューニングするのではなく、観測できる事実をもとにボトルネックを特定することが重要です。
重い理由が分かれば、対策はかなり明確になります。

  • 実行時間を悪化させる代表的な要因
  • 計測によって原因を切り分ける手順
  • 設定、コード、運用の各レイヤーで効く改善策
  • 速度向上と安定性を両立する考え方

なんとなく wait を減らす、なんとなく worker 数を増やす。
その場しのぎの最適化では、別の箇所で不安定さが増すこともあります。
必要なのは、テスト実行系をひとつのシステムとして捉える視点です。
Playwrightのパフォーマンス改善を、再現性のある形で進めたい方に向けて、実践的に掘り下げます。

  1. Playwrightのテストが重いと感じるのはなぜか
    1. E2Eテストの実行時間が開発効率に与える影響
    2. 重さの原因を感覚ではなく構造で捉える重要性
  2. Playwrightのパフォーマンス低下を招く典型的な原因
    1. 不要なwaitと過剰なタイムアウト設定
    2. テストごとのブラウザ起動とコンテキスト生成コスト
    3. 認証処理や初期データ投入の重複
    4. 不安定なセレクタとリトライ増加の悪循環
  3. まず確認したいPlaywrightテストの計測ポイント
    1. テスト全体と単体ケースの実行時間を切り分ける
    2. trace・report・ログからボトルネックを可視化する
    3. CIとローカルで異なる遅延要因を見分ける
  4. 重い原因を効率よく特定する切り分け手順
    1. 実行環境・テストコード・アプリ側の3層で考える
    2. 1つずつ条件を固定して再現性を確認する
    3. 速さだけでなく失敗率も合わせて評価する
  5. Playwright設定の見直しで実行速度を改善する方法
    1. workers・projects・retriesの最適化ポイント
    2. storageStateの活用でログイン処理を省略する
    3. タイムアウト設定を現実的な値に調整する
  6. テストコードの書き方を変えて高速化する実践テクニック
    1. waitForTimeout依存をやめて適切な待機条件に置き換える
    2. 再利用可能なfixtureで初期化コストを抑える
    3. 重複処理を減らしてテストケースをスリム化する
  7. CI環境でPlaywrightテストを安定かつ高速に回す工夫
    1. CPU・メモリ制約を前提に並列数を調整する
    2. キャッシュ戦略で依存関係の準備時間を短縮する
    3. 失敗時だけ詳細ログを残す運用で無駄を減らす
  8. 高速化しても品質を落とさないための設計視点
    1. 速いが壊れやすいテストを避ける考え方
    2. 保守しやすいE2Eテスト構成を維持するコツ
  9. Playwrightのテストが重い原因を特定して改善を継続するまとめ

Playwrightのテストが重いと感じるのはなぜか

Playwrightのテスト実行時間の増加要因を分析する開発環境のイメージ

Playwrightは、モダンなWebアプリケーションのE2Eテストを効率よく自動化できる優れたツールです。
ところが、導入直後は快適に動いていたとしても、テストケースが増え、検証対象の画面や操作が広がるにつれて、「急に重くなった」と感じる場面が増えていきます。
これは気のせいではありません。
Playwrightのテストは、単なる関数の実行ではなく、ブラウザ起動、画面描画、ネットワーク通信、DOM状態の待機、認証、データ準備といった複数の処理を含むため、規模の拡大に伴って負荷が目に見えて増えやすい性質があります。

特に注意したいのは、重さの正体が一つではないことです。
テストの本数が増えたから遅い、という理解だけでは改善につながりません。
実際には、1件ごとの実行時間が少しずつ伸び、その小さな遅延が全体で大きな待ち時間へ変わっていくことが多いのです。
つまり問題は件数そのものだけでなく、実行の構造にあります。
ここを見誤ると、並列数だけ増やして不安定になったり、待機を削ってテストが壊れやすくなったりします。
必要なのは、遅さを感覚ではなく分解可能な現象として扱う視点です。

E2Eテストの実行時間が開発効率に与える影響

E2Eテストの実行時間は、単にCIの終了を待つ時間という話ではありません。
開発者の意思決定の速度そのものに影響します。
たとえば、コードを修正してから結果が分かるまでに長い時間がかかると、修正と確認のループが間延びします。
すると、直前に何を変更したのか、どの仮説を検証していたのかという思考の文脈が薄れ、判断の精度も落ちやすくなります。
フィードバックが遅いシステムは、それだけで生産性を下げるのです。

また、テストが重い環境では、実行回数そのものが減る傾向があります。
毎回フルで回すのが負担になるため、ローカル確認を省略したり、影響範囲を狭く見積もって一部だけ確認したりする判断が起きやすくなります。
その結果、問題の検出が後ろ倒しになり、CI上でまとめて失敗する。
修正コストの増大です。

影響は次のように整理できます。

  • ローカルでの試行回数が減る
  • CI待ち時間が長くなりレビューが滞る
  • 不具合の発見タイミングが遅れる
  • 修正と検証の往復回数が増える
  • 開発者がテスト実行自体を避けやすくなる

ここで重要なのは、テスト時間の増加は線形な不便ではなく、開発フロー全体に波及するという点です。
10分待つこと自体が問題なのではありません。
10分待つことで、実行頻度、集中力、レビュー速度、障害検知の早さまで連鎖的に悪化することが本質です。
重いテストは、見えにくい形でチームのスループットを削ります。
だからこそ、単なる体感の不満として片付けるべきではありません。

重さの原因を感覚ではなく構造で捉える重要性

Playwrightの高速化で失敗しやすいのは、「たぶんここが遅いはずだ」という推測から調整を始めてしまうことです。
しかし、パフォーマンス問題はしばしば直感に反します。
見た目には短そうな処理が積み重なって支配的なボトルネックになっていることもあれば、逆に重そうに見える処理が実は全体への影響が小さいこともあります。
つまり、最適化は印象ではなく観測から始めるべきです。

構造で捉えるとは、テスト実行を要素に分けて考えることです。
たとえば、以下のような層に分解できます。

層 主な要素 遅延の起点
実行環境 CPU、メモリ、CIリソース 並列不足、競合、性能不足
テスト設定 workers、retries、timeout 過剰待機、設定不整合
テストコード wait、selector、fixture 重複処理、非効率な待機
アプリ側 API応答、描画、認証 本番同様の遅さ、依存先の遅延

このように分解すると、「Playwrightが重い」のではなく、「どの層の何が実行時間を押し上げているのか」という問いに変わります。
この問いに変換できた時点で、改善はかなり進めやすくなります。
問題設定の明確化です。

さらに、構造化して考える利点は、対策の副作用も読みやすくなることです。
たとえば、固定待機を減らすのは有効ですが、状態確認を伴わずに単純削除すると不安定化します。
並列実行を増やすのも有効ですが、テストデータが競合する設計なら逆効果です。
つまり、改善策は個別最適ではなく、依存関係を含めて評価する必要があります。
ここに論理的な切り分けの価値があります。

結局のところ、Playwrightのテストが重いと感じる背景には、件数増加だけでは説明できない構造的な複雑さがあります。
そして、その複雑さを曖昧な経験則で処理しようとすると、改善の再現性が失われます。
だからこそ、まず必要なのは「どこが遅いのか」ではなく、「何層のどの処理が、どう積み上がって遅さを作っているのか」を整理することです。
そこから先に、本当に効く最適化が見えてきます。

Playwrightのパフォーマンス低下を招く典型的な原因

Playwrightテストを遅くする複数要因を一覧化したイメージ

Playwrightのテストが遅くなると、多くの場合は「ケース数が増えたから」と説明されがちです。
しかし実際には、件数の増加はきっかけにすぎず、真の問題は各テストの内部に潜む小さな非効率の蓄積にあります。
1件あたり数百ミリ秒から数秒の無駄でも、数十件、数百件と積み上がれば、全体では無視できない差になります。
しかも厄介なのは、その遅延が単独で存在するのではなく、待機、起動、認証、セレクタ不安定性のような複数要因が相互に影響し合う点です。
ここを曖昧にしたまま対策すると、改善したつもりが別の箇所で失速することもあります。
まずは、典型的な原因を構造的に押さえることが重要です。

不要なwaitと過剰なタイムアウト設定

最も頻出で、しかも見落とされやすいのが不要な待機です。
特に waitForTimeout() のような固定待機は、短期的には手軽でも、長期的にはテスト全体を確実に重くします。
固定待機は、必要な時間だけ待つのではなく、毎回指定した時間を機械的に消費するためです。
画面がすでに描画済みでも、API応答がすでに完了していても、待機は短縮されません。
つまり、状態に基づかない待機は、成功時にも無駄が発生する設計です。

たとえば、1テストで2秒の固定待機を3回使えば、それだけで6秒です。
これが50件あれば300秒、すなわち5分になります。
小さな待機の合計が、全体のボトルネックになる典型例です。

また、タイムアウト設定も同様です。
タイムアウトは失敗時の保険として必要ですが、過剰に大きい値を安易に設定すると、異常系での失敗検知が極端に遅れます。
さらに、遅い原因を隠してしまう副作用もあります。
本来ならすぐに落ちるべき不安定な操作が、長時間の待機の末にたまたま成功し、問題の所在が曖昧になることもあります。
結果として、速さも安定性も両方悪化しやすい構図です。

重要なのは、待つこと自体が悪いのではなく、何を条件に待つかです。
Playwrightは本来、要素の表示や操作可能状態を待つ仕組みが強いツールです。
にもかかわらず、状態待機ではなく時間待機に寄せると、その利点を自分で捨てることになります。
設計上の損失です。

テストごとのブラウザ起動とコンテキスト生成コスト

次に大きいのが、ブラウザ起動やコンテキスト生成の繰り返しです。
Playwrightではテスト分離のためにブラウザコンテキストを分ける設計が重要ですが、必要以上に生成と破棄を繰り返すと、その初期化コストが支配的になります。
特に、テストごとに毎回ブラウザをフル起動し、ログイン前提のセットアップまで含めて実行している場合、アプリ本体の検証時間より準備時間の方が長い、という逆転が起こりえます。

ここで考えるべきなのは、分離の粒度です。
すべてを完全に独立させる設計は一見安全ですが、そのぶん起動コストを各ケースが負担します。
一方で、共有しすぎるとテスト間依存が発生します。
したがって、何を共有し、何を分離するかを明示的に設計しなければなりません。
ブラウザ、コンテキスト、ページ、認証状態。
それぞれのライフサイクルが性能に直結します。

遅延の発生源を整理すると、主に次のようになります。

  • ブラウザプロセスの起動
  • 新規コンテキストの生成
  • 初期ページの読み込み
  • 共通セットアップの再実行
  • テスト終了ごとのクリーンアップ

これらは1回では小さく見えても、全ケースで発生すると大きくなります。
特にCIではCPUやメモリが潤沢ではないため、起動処理の繰り返しがさらに重く感じられます。
速度低下の累積要因です。

認証処理や初期データ投入の重複

ログインやテストデータ投入も、Playwrightの実行時間を押し上げる代表要因です。
多くの現場では、各テストの独立性を担保するために、毎回ログインし、必要なデータを作成し、初期状態を整える実装が書かれます。
この方針自体は理解できますが、すべてのケースで同じ準備を毎回繰り返す設計は非効率です。
準備処理が本体化する現象です。

たとえば、認証が外部APIや複数画面遷移を伴う場合、1回のログインだけでも相応の時間がかかります。
さらに、テストデータ作成がDB更新や管理画面操作を含む場合、そのオーバーヘッドは無視できません。
こうした処理がテストの数だけ繰り返されると、アプリの本質的な振る舞いを検証する前に時間が消えていきます。

問題は、重複そのものだけではありません。
重複準備は失敗点も増やします。
認証APIが不安定なら、検証対象とは無関係の場所で失敗します。
初期データ投入が遅ければ、タイムアウトの温床になります。
つまり、重複準備は速度だけでなく、ノイズ源にもなりやすいのです。
高速化と安定化の両面から見直す価値があります。

不安定なセレクタとリトライ増加の悪循環

最後に見逃せないのが、不安定なセレクタです。
セレクタが曖昧だったり、表示タイミングに依存していたりすると、Playwrightは要素を見つけるために内部で待機や再試行を繰り返します。
この自動待機は本来便利な仕組みですが、セレクタ設計が悪いと、その利点が遅延の温床に変わります。

たとえば、DOM構造に強く依存した長いセレクタや、文言変更に弱い指定は、保守性だけでなく実行速度にも悪影響を与えます。
要素の特定に時間がかかるだけでなく、見つかったとしても別要素を拾う危険があります。
その結果、クリック失敗、再描画待ち、リトライ増加という流れが生まれます。
これが悪循環です。

この問題は表面上、単なる flaky test に見えることがあります。
しかし内部では、各失敗の前に細かな待機が積み重なっています。
つまり、不安定なセレクタは「たまに落ちる問題」であると同時に、「普段から遅くする問題」でもあります。
安定性の問題と性能問題は、ここで分離できません。

Playwrightのパフォーマンス低下は、派手な一因ではなく、日常的な実装判断の積み重ねから生まれることが多いです。
不要な待機、過剰な初期化、重複認証、曖昧なセレクタ。
どれも単体では些細に見えるかもしれません。
しかし、E2Eテストは繰り返し実行される仕組みである以上、小さな非効率ほど全体では深刻になります。
だからこそ、まずは典型的な原因を具体的に認識し、どの層で時間が失われているのかを切り分けることが、改善の第一歩になります。

まず確認したいPlaywrightテストの計測ポイント

Playwrightの実行時間を測定するための主要指標を整理したイメージ

Playwrightのテストが重いと感じたとき、すぐに設定変更やコード修正へ進みたくなるかもしれません。
しかし、計測なしの最適化は再現性が低く、改善したつもりで別のボトルネックを増幅させることもあります。
パフォーマンス改善の出発点は、どこで時間が失われているのかを観測可能な形で捉えることです。
これはソフトウェア性能の基本原則でもあります。
遅いという印象を、分解可能な数値へ変換する作業。
ここを丁寧に行うことで、原因の切り分けが一気に進みます。

重要なのは、Playwrightの実行時間をひとつの塊として見ないことです。
全体が遅いのか、特定のケースだけが遅いのか。
ローカルでは速いのにCIだけ遅いのか。
待機が長いのか、セットアップが長いのか。
観測の粒度を上げるほど、対策は具体化します。
逆に、総実行時間だけ見ていると、どこを直せばよいか判断できません。
計測とは、問題を小さくし、解像度を上げる行為です。

テスト全体と単体ケースの実行時間を切り分ける

最初に見るべきなのは、全体時間と個別時間の関係です。
たとえばテストスイート全体が20分かかっているとしても、その原因が「すべてのケースが少しずつ遅い」のか、「数件だけ極端に遅い」のかで対応はまったく変わります。
前者なら共通セットアップや固定待機を疑うべきですし、後者なら特定画面や外部依存のあるケースを重点的に調べるべきです。
つまり、平均ではなく分布を見る視点が必要です。

実務では、次の切り口で切り分けると有効です。

  • 総実行時間
  • ファイル単位の実行時間
  • テストケース単位の実行時間
  • beforeEach や fixture など準備処理の時間
  • 失敗ケースと成功ケースの時間差

特に見逃しやすいのが、準備処理の比率です。
各テスト本体は短いのに、ログインや初期化に時間を使っているケースは少なくありません。
その場合、テストケースのロジックを改善しても効果は限定的です。
どのフェーズが支配的かを切り分ける必要があります。

また、単体ケースの時間を見るときは、単純な実行時間だけでなく、ばらつきにも注目すべきです。
毎回ほぼ同じ時間で終わるケースと、速いときもあれば遅いときもあるケースでは、原因が異なります。
前者は構造的な重さ、後者はネットワークやレンダリング、競合状態などの不安定要因が疑われます。
時間の平均値だけではなく、安定性も観測対象です。

trace・report・ログからボトルネックを可視化する

数値で遅いケースを特定できたら、次は中身を可視化します。
ここで有効なのが、trace、report、ログの3点です。
Playwrightの強みは、失敗したかどうかだけでなく、テスト中に何が起きていたかを比較的細かく観測できることにあります。
つまり、遅延の原因を推測でなく履歴で追えるわけです。

traceでは、各操作がいつ実行され、何を待ち、どこで時間を消費したかを時系列で確認できます。
クリック後に画面遷移が遅いのか、要素待機で止まっているのか、ネットワーク応答待ちなのか。
こうした差は、ログだけでは見えにくい部分です。
一方、reportは全体傾向を見るのに向いています。
どのテストファイルが長いか、どのケースが繰り返し遅いかを俯瞰できます。
ログはさらに細かい補助線として機能します。
特定のAPI呼び出し前後、fixture開始と終了、認証完了時刻などを記録しておけば、traceだけでは分かりにくいアプリ側の遅延も追いやすくなります。

観測対象を整理すると、主に次の通りです。

観測手段 向いている用途 見るべきポイント
trace 個別ケースの詳細分析 待機箇所、操作順、画面遷移
report 全体傾向の把握 長いテスト、失敗傾向、分布
ログ 任意ポイントの補足観測 API時間、初期化時間、条件分岐

可視化の価値は、遅さの所在を言語化できることです。
たとえば「なんとなくログインが遅い」ではなく、「認証後のダッシュボード描画で毎回2.5秒待っている」と表現できれば、対策は明確になります。
問題の名前が変わる瞬間です。

CIとローカルで異なる遅延要因を見分ける

Playwrightの計測で忘れてはならないのが、実行環境差です。
ローカルでは問題なくても、CIでは急に遅くなる。
あるいはその逆。
この差を無視すると、正しい対策にたどり着けません。
なぜなら、ローカルとCIではCPU、メモリ、ストレージ速度、ネットワーク条件、同時実行の競合状況が大きく異なるからです。
同じテストコードでも、置かれた環境によってボトルネックは変わります。

ローカルで速いのにCIで遅い場合、まず疑うべきはリソース制約です。
workers を増やしすぎてCPU競合が起きていないか、ブラウザ起動が集中していないか、依存関係のインストールやキャッシュ復元が想定以上に時間を使っていないか。
逆に、ローカルだけ遅い場合は、開発中の他プロセス、拡張機能、デバッグ設定、手元のネットワーク環境などが影響していることもあります。

ここで大切なのは、ローカルとCIを同じ物差しで見ないことです。
比較は必要ですが、同一視は危険です。
環境ごとに次の観点を切り分けると分析しやすくなります。

  • マシンスペックの差
  • 並列実行時の競合
  • ネットワーク依存の強さ
  • キャッシュの有無
  • ログやtrace取得設定の違い

もしCIだけで遅いなら、コードより運用設定に原因がある可能性も高まります。
もし両方で遅いなら、テスト構造そのものに問題がある確率が高い。
こうして実行場所ごとに原因候補を狭めていくことが重要です。

Playwrightのパフォーマンス改善は、感覚で「ここが怪しい」と当てにいく作業ではありません。
全体時間と個別時間を分け、traceとreportとログで中身を見て、さらにCIとローカルの差を環境要因として切り分ける。
この順序で観測すると、遅さはかなり具体的な問題に変わります。
計測は遠回りに見えて、実は最短経路です。
何を直すべきかが分かれば、不要な最適化を避けながら、効果の大きい改善に集中できます。

重い原因を効率よく特定する切り分け手順

テスト高速化のために原因を順序立てて切り分けるイメージ

Playwrightのテストが重いと分かったあと、次に重要になるのは、どの順序で原因を絞り込むかです。
ここを誤ると、改善作業が場当たり的になります。
たとえば、並列数を増やしてみる、不要そうな待機を消してみる、タイムアウトを短くしてみる。
こうした対応がたまたま効くこともありますが、再現性は低く、別の問題を生む可能性もあります。
性能改善は、試行錯誤の量で勝つものではありません。
どの仮説を、どの粒度で、どの順番に検証するか。
その切り分け設計が重要です。

特にE2Eテストは、ブラウザ、テストコード、対象アプリ、外部API、CI基盤といった複数の要素が重なって動きます。
つまり、遅いという現象の背後には、異なる層の原因が同時に潜んでいることがあります。
したがって、効率よく特定するには、原因候補を構造的に分け、条件を一つずつ固定し、速度と安定性の両面から評価する必要があります。
問題を小さくしながら確かめる。
基本ですが、最も効果的な方法です。

実行環境・テストコード・アプリ側の3層で考える

重さの原因を探すときは、まず「どの層の問題か」を切り分けるべきです。
Playwright自体が遅いのではなく、その周辺のどこかに待ち時間の発生源があります。
ここを曖昧にしたまま分析すると、アプリ側の遅延をテストコードの問題と誤認したり、CI環境の制約をPlaywright設定で解決しようとしたりして、改善が遠回りになります。

実務では、次の3層で考えると整理しやすくなります。

層 主な対象 典型的な遅延要因
実行環境 ローカル、CI、CPU、メモリ、I/O リソース不足、並列競合、キャッシュ不備
テストコード fixture、wait、selector、retry 重複処理、固定待機、不安定な操作
アプリ側 API、DB、描画、認証、画面遷移 応答遅延、初期表示負荷、外部依存

この3層で見る利点は、責務の境界が明確になることです。
たとえば、特定のテストだけローカルでもCIでも遅いなら、テストコードかアプリ側の可能性が高い。
一方、CIだけが全体的に遅いなら、実行環境の影響が強いと考えられます。
つまり、症状の出方から層を推定できるわけです。

また、この分け方は議論にも向いています。
チームで原因を共有するときに、「遅いです」では議論が進みません。
しかし、「CIのCPU競合が強そうです」「ログイン後の初期表示でアプリ側が2秒止まっています」「selectorの再試行が増えています」と層ごとに表現できれば、誰がどこを直すべきかが見えます。
問題の所有範囲が明確になることも、切り分けの価値です。

1つずつ条件を固定して再現性を確認する

原因調査で避けたいのは、複数の条件を同時に動かすことです。
workersを変えながら待機も削り、さらにfixtureも変える。
これでは、何が効いたのか分かりません。
性能問題の検証では、変数を一つずつ操作することが基本です。
これは実験設計としても自然な考え方です。

たとえば、次のような順序が有効です。

  1. 実行対象を最小限に絞る
  2. 同じケースを複数回走らせて時間のばらつきを見る
  3. 並列数を固定したまま、待機や初期化だけを見直す
  4. テストコードを固定したまま、実行環境だけを変える
  5. アプリの応答をモック化して差分を見る

この手順の狙いは、変化の原因を一意に近づけることです。
たとえば、アプリの外部API応答をモックにしただけで速度が大きく改善するなら、問題はPlaywrightではなく依存先の応答時間にある可能性が高まります。
逆に、モック化しても遅いなら、テストコードや画面描画、あるいはブラウザ操作の構造を疑うべきです。
条件固定の価値は、原因候補を潰していける点にあります。

また、再現性の確認も重要です。
ある一回だけ速くなった、あるいは遅くなったという結果は、ノイズかもしれません。
少なくとも複数回の実行で傾向を見て、改善が安定しているかを確かめる必要があります。
性能改善は、偶然ではなく持続的な差として確認されて初めて意味を持ちます。
単発の成功では不十分です。

速さだけでなく失敗率も合わせて評価する

パフォーマンス改善で意外と見落とされやすいのが、失敗率とのトレードオフです。
テストを速くすることだけを目的にすると、短期的には見た目の実行時間が縮むことがあります。
しかし、その代償として flaky test が増えれば、結果としてチーム全体の時間はむしろ失われます。
再実行、原因調査、レビュー待ち、信頼低下。
こうしたコストは、単純な秒数以上に重いものです。

たとえば、固定待機を削除して1件あたり500ミリ秒短縮できたとしても、要素安定前のクリック失敗が増えれば意味がありません。
同様に、リトライ回数を下げて見かけの総時間を縮めても、本来吸収できていた一時的失敗が表面化するなら、運用上の負担は増えます。
重要なのは、速くなったかどうかではなく、速くなっても信頼できるかどうかです。

そのため、改善を評価するときは次の2軸で見るべきです。

  • 実行時間がどれだけ減ったか
  • 成功率、再現性、失敗の偏りがどう変わったか

理想は、速度と安定性の両立です。
もし両立できないなら、どこまでの速度向上なら品質を損なわないかを判断する必要があります。
ここで大切なのは、速さを絶対善とみなさないことです。
E2Eテストの価値は、単に短時間で終わることではなく、期待する振る舞いを信頼できる形で検証することにあります。
性能改善も、その目的に従属すべきです。

重い原因を効率よく特定するには、思いつきで設定を変えるのではなく、層で分け、条件を固定し、速度と失敗率を同時に観測することが重要です。
この進め方は一見地味ですが、最も無駄が少なく、改善の説明責任も果たしやすい方法です。
Playwrightの最適化で本当に必要なのは、特別な裏技ではありません。
問題を構造化し、仮説を丁寧に検証する姿勢です。
そこに再現性のある改善があります。

Playwright設定の見直しで実行速度を改善する方法

Playwright設定を最適化してテスト速度を改善するイメージ

Playwrightのテストが重いとき、まずコードの書き方に目が向きがちですが、設定の見直しだけでも実行速度が大きく改善することがあります。
むしろ、テストコードを細かく修正する前に、設定レイヤーで明らかな非効率を除去したほうが、少ない変更で大きな効果を得やすい場面もあります。
なぜなら、設定は全テストに横断的に効くためです。
1件のケースだけでなく、スイート全体の挙動を変えられる。
ここが大きい点です。

ただし、設定改善は数値を小さくすればよいという話ではありません。
workersを増やせば速くなるとは限らず、retriesを減らせば健全とも限りません。
重要なのは、テストの実態と実行環境に合わせて、設定値を論理的に整えることです。
Playwrightの設定は、速度、安定性、再現性のバランスを取るための制御面です。
ここを適当に扱うと、見かけの短縮と引き換えに不安定さを増やしてしまいます。
設定は最適化の近道である一方、誤ると全体へ副作用を広げる領域でもあります。

workers・projects・retriesの最適化ポイント

最初に見直したいのが、workers、projects、retriesです。
これらはテスト実行時間に直結しやすく、しかも影響範囲が広い設定です。
特にworkersは分かりやすいため、「重いなら増やせばよい」と考えられがちですが、実際には単純ではありません。
workersは並列数を増やす設定であり、CPUやメモリ、I/Oに十分な余力がある場合には有効です。
しかし、CI環境のリソースが限られている場合、増やしすぎるとブラウザプロセス同士が競合し、かえって遅くなることがあります。
並列化は常に加速ではなく、飽和点を持つ最適化です。

projectsも同様です。
複数ブラウザや複数デバイス設定を一度に走らせれば、網羅性は上がりますが、そのぶん総時間は当然増えます。
ここで考えるべきなのは、すべての変更に対して全projectsが必要かどうかです。
回帰確認の目的と、日常開発で欲しいフィードバック速度は同じではありません。
毎回全組み合わせを回す設計は、品質面では安心でも、運用面では重くなりやすい。
したがって、日常実行用とフル検証用を分ける設計も有効です。

retriesも誤解されやすい項目です。
retriesが多いほど安定するように見えますが、実際には不安定なテストを見えにくくし、失敗時の時間コストを増やします。
もちろん一時的な環境揺らぎを吸収する意義はありますが、常に複数回再試行する前提は望ましくありません。
retryは問題の解決策ではなく、運用上の緩衝材です。
この認識が重要です。

設定見直しでは、次の観点を持つと整理しやすくなります。

  • workersはマシンスペックに対して過剰でないか
  • projectsは本当に常時必要な組み合わせか
  • retriesが不安定なテストを隠していないか
  • 速度改善と失敗率悪化のどちらが起きているか

つまり、設定値は大きいか小さいかではなく、妥当かどうかで評価すべきです。
数値の意味を文脈の中で捉える必要があります。

storageStateの活用でログイン処理を省略する

Playwrightの実行時間で非常に支配的になりやすいのが、ログイン処理の繰り返しです。
特に認証がUI経由で実装されている場合、各テストが毎回ログイン画面を開き、入力し、遷移し、認証後ページを待つという流れを繰り返すことになります。
これは独立性の観点では分かりやすい一方、パフォーマンス面ではかなり非効率です。

ここで有効なのがstorageStateです。
あらかじめ認証済み状態を保存し、それを各テストで再利用することで、毎回のログインを省略できます。
この方法の利点は、単なる高速化だけではありません。
認証画面自体の不安定さや、外部認証基盤の一時的遅延の影響を減らせる点にもあります。
つまり、速度と安定性の両方に効く可能性があるわけです。

ただし、何でもstorageStateに寄せればよいわけではありません。
認証そのものを検証対象にしたいテストまで省略してしまうと、本来確認すべき振る舞いを失います。
そのため、認証機構を検証するテストと、認証済み前提で業務機能を検証するテストを分ける設計が重要です。
責務分離です。

また、storageState運用では、状態の鮮度や権限差にも注意が必要です。
期限切れのセッション、変更された権限、テナント差異などを無視すると、速くはなっても誤った前提でテストすることになります。
ここでも、速度だけでなく妥当性を維持できているかが問われます。
省略してよい処理と、省略すべきでない処理の切り分け。
設定活用の本質です。

タイムアウト設定を現実的な値に調整する

タイムアウト設定も、実行速度に大きな影響を持つ重要項目です。
特に問題なのは、「失敗すると困るから長めにしておく」という発想で、全体的に過大なタイムアウトを設定してしまうことです。
これをすると、異常時の失敗検知が遅れます。
つまり、正常時には目立たなくても、失敗時に時間が一気に失われます。
E2Eテストでは、一つの不具合が後続処理に連鎖することもあるため、この遅延は総時間に強く響きます。

現実的な値に調整するとは、対象処理の性質に応じて必要十分な範囲を見積もることです。
たとえば、通常1秒以内に応答するUI操作に30秒の待機を許していれば、問題の検知が遅すぎます。
一方で、初回セットアップや外部依存のある処理に対して過度に短い値を入れると、今度は不要な失敗が増えます。
したがって、すべてを一律に短くするのではなく、処理の種類ごとに妥当な水準を考える必要があります。

実務上は、次のような発想が有効です。

設定対象 長すぎる場合の問題 短すぎる場合の問題
テスト全体 失敗検知が遅い 本来通るケースまで落ちる
要素待機 無駄な待機が増える 描画揺らぎに弱くなる
ナビゲーション 異常時に長時間停止する 通信遅延時に不安定化する

このように、タイムアウトは保険であると同時に、失敗コストを決める設定でもあります。
だからこそ、漫然と長くするのではなく、計測結果に基づいて現実的に調整すべきです。

Playwright設定の見直しは、派手な最適化ではありません。
しかし、workers、projects、retries、storageState、タイムアウトといった基本設定を整えるだけで、テストスイート全体の速度と安定性は大きく変わります。
重要なのは、設定を魔法の数値として扱わないことです。
どの設定がどの遅延を生み、どの設定がどの不安定さを抑えているのか。
その因果関係を意識して調整すれば、設定は単なるオプションではなく、性能設計の手段になります。

テストコードの書き方を変えて高速化する実践テクニック

テストコード改善によってPlaywrightを高速化する実践イメージ

Playwrightの実行速度を改善するうえで、設定の見直しは確かに有効です。
しかし、一定以上の規模になると、最終的に効いてくるのはテストコードそのものの書き方です。
なぜなら、設定は全体の枠組みを整えるものであり、個々のテストが持つ非効率までは消してくれないからです。
各ケースの内部で無駄な待機や重複した準備処理が残っていれば、いくらworkersやretriesを調整しても改善幅には限界があります。
つまり、速度改善を持続的なものにするには、テストコードの構造を見直す必要があります。

ここで重要なのは、短く書くこと自体が目的ではないという点です。
コード行数が少なくても遅いテストはありますし、逆に処理の意図が明確で再利用しやすいコードは、多少長くても結果的に速く安定します。
問うべきなのは、どの操作が本当に必要で、何が繰り返され、どこで待ちすぎているかです。
つまり、高速化の本質は省略ではなく整理です。
構造的な整理。
その観点から、特に効果が出やすい実践ポイントを見ていきます。

waitForTimeout依存をやめて適切な待機条件に置き換える

テストを素早く書きたい場面では、waitForTimeout() に頼りたくなることがあります。
画面更新が不安定なとき、とりあえず1秒待てば通る。
こうした対処は短期的には便利です。
しかし、長期的には確実にパフォーマンスを悪化させます。
固定時間待機は、必要な時間だけ待つのではなく、毎回必ず指定秒数を消費するためです。
しかも、環境差による揺らぎに弱く、速さと安定性の両面で不利になりやすい。
典型的な技術的負債です。

Playwrightは、もともと状態ベースの待機に強い設計を持っています。
要素が表示されたか、操作可能になったか、URLが変わったか、リクエストが完了したか。
こうした観測可能な条件に基づいて待機すれば、不要な時間を省きつつ、環境差にも対応しやすくなります。
重要なのは「何秒待つか」ではなく、「何が成立するまで待つか」です。
待機対象の意味づけです。

たとえば、高速化の観点では次のような置き換えが有効です。

  • 固定秒数待機を、要素の表示待機に変える
  • 画面遷移後の待機を、URL変化や特定テキストの出現待機に変える
  • API結果依存の画面更新を、レスポンス完了や状態変化の確認に変える

この違いは小さく見えて、全体では大きな差になります。
固定待機は成功時にも失敗時にも時間を使いますが、条件待機は満たされた時点で次へ進めます。
つまり、速い環境では短く、遅い環境では必要な範囲だけ待つ。
合理的です。

また、条件待機へ移行することは、速度改善だけでなく不具合発見にもつながります。
固定待機でごまかしていた画面不安定性が可視化されるからです。
これは一見面倒に思えるかもしれませんが、むしろ好ましいことです。
問題を遅らせるのではなく、明示的に検出できる状態へ持ち込めるためです。

再利用可能なfixtureで初期化コストを抑える

初期化コストの削減では、fixture設計が重要です。
多くのPlaywrightテストでは、ログイン、テストデータの準備、画面遷移、共通オブジェクト生成といった初期化処理が繰り返されます。
これを各テストの中に直接書いていると、処理の重複が増えるだけでなく、修正時の影響範囲も広がります。
そして当然、実行時間も伸びやすくなります。
初期化が分散している状態は、性能面でも保守面でも不利です。

fixtureを再利用可能な形で設計すれば、この問題をかなり抑えられます。
共通準備を一箇所へ寄せることで、毎回必要な処理と、共有してよい処理を整理しやすくなるからです。
たとえば、認証済みページの準備、特定ロールのユーザー生成、共通ナビゲーションの到達といった流れは、個別ケースで繰り返すよりfixture化した方が効率的です。

ただし、fixtureは共通化すればするほどよいわけではありません。
過剰に大きなfixtureは、使わない処理まで毎回実行する原因になります。
さらに、テストの前提条件が見えにくくなり、デバッグもしづらくなります。
つまり、fixtureの設計では再利用性と軽量性の両立が必要です。
共有するべき処理と、ケース固有の処理を混ぜないこと。
ここが重要です。

考え方としては、次のように整理するとよいです。

対象 fixture化に向くか 理由
認証済み状態 向く 多くのケースで共通しやすい
共通ページ遷移 向く 手順重複を減らせる
特定ケース専用の複雑な準備 向きにくい 汎用化コストが高い
条件分岐の多い一括初期化 向きにくい 不要処理が増えやすい

fixtureは便利な抽象化ですが、性能改善の観点では「必要な準備だけを最短で供給する仕組み」として設計すべきです。
共通化のための共通化ではなく、コスト削減のための共通化。
そこが本質です。

重複処理を減らしてテストケースをスリム化する

最後に重要なのが、テストケース自体をスリムに保つことです。
ここでいうスリム化とは、単に短く書くことではありません。
同じ目的に対して、同じ準備、同じ遷移、同じ確認が繰り返されていないかを見直すことです。
E2Eテストでは、画面をまたぐ操作が多いため、何も意識しないと似た処理が各所に散らばります。
その結果、修正対象が増え、実行時間も積み上がります。

たとえば、複数のテストが毎回トップページから入り、同じメニューをたどって同じ一覧画面まで移動しているなら、その構成は本当に必要かを考えるべきです。
検証対象が一覧画面以降にあるなら、そこまでの到達を共通化する、あるいは前提状態として扱う余地があります。
もちろん、ユーザー動線そのものを検証したいケースなら意味がありますが、すべてのテストで同じ導線を踏む必要はありません。
目的ごとに到達経路を最適化する視点が必要です。

また、重複処理は時間だけでなくノイズも増やします。
テスト対象と無関係の途中操作が多いほど、失敗点も増えます。
つまり、スリムなテストは速いだけでなく、失敗箇所の特定もしやすくなります。
観測性の向上です。

見直すべき観点を挙げると、次のようになります。

  • 毎回同じ画面遷移を繰り返していないか
  • 同じデータ準備を複数ケースで重複していないか
  • ひとつのテストで確認項目を詰め込みすぎていないか
  • 検証目的と無関係な操作が含まれていないか

Playwrightの高速化は、特別なテクニックだけで達成されるものではありません。
固定待機を条件待機へ置き換え、fixtureを適切に使い、重複した準備や操作を減らす。
こうした基本的なコード設計の積み重ねが、最終的には大きな差になります。
重要なのは、テストコードを一時的に通すためのスクリプトとしてではなく、継続的に実行されるソフトウェアとして扱うことです。
その視点を持てば、高速化は偶然の産物ではなく、設計の結果になります。

CI環境でPlaywrightテストを安定かつ高速に回す工夫

CI上でPlaywrightテストを安定高速化する運用イメージ

Playwrightのテストをローカルで快適に動かせていても、CIに載せた途端に急に遅くなったり、不安定になったりすることがあります。
これは珍しい現象ではありません。
むしろE2Eテストでは自然なことです。
なぜなら、CI環境は開発マシンよりも利用できるCPUやメモリが限られていることが多く、さらに同時実行されるジョブやキャッシュ状況、ストレージ性能、ネットワーク条件なども毎回一定ではないからです。
つまり、CIでは「速さ」だけでなく「環境変動に耐える設計」が求められます。
ここを理解せずにローカル前提の調整をそのまま持ち込むと、速度改善どころか失敗率の上昇につながりやすくなります。

CI最適化で重要なのは、単純な高速化ではありません。
限られた計算資源の中で、必要な情報だけを残し、無駄な準備を減らし、失敗時にだけ詳細な観測を行うことです。
言い換えるなら、実行資源の配分設計です。
Playwrightそのものを速くするというより、CI全体の流れの中でテストをどう効率よく走らせるかを考える必要があります。

CPU・メモリ制約を前提に並列数を調整する

CIで最も誤解されやすいのが並列数の扱いです。
Playwrightは workers によって並列実行できるため、直感的には多いほど速そうに見えます。
しかし、CI環境ではこの前提が簡単に崩れます。
CPUコア数が少ない、メモリが限られている、他ジョブと資源を共有している。
この条件下でブラウザを過剰に同時起動すると、コンテキスト切り替えやメモリ競合が増え、結果として全体が遅くなることがあります。
並列化の逆効果です。

ここで大切なのは、理論上の最大並列数ではなく、実測上の最適並列数を探ることです。
たとえば、8並列が設定上可能でも、実際には4並列のほうが安定して速いケースは珍しくありません。
特にPlaywrightはブラウザ実行を伴うため、単なるスクリプト処理より資源消費が大きい傾向があります。
したがって、CIでは「余っているCPUを使い切る」発想ではなく、「競合を起こさない範囲で最も効率が高い点を見つける」発想が重要です。
最適化とは上限まで使うことではなく、飽和前で止めることです。

実際の調整では、次の観点で見ると判断しやすくなります。

  • workersを増やしたときに総時間が本当に短くなっているか
  • 失敗率や再試行率が同時に上がっていないか
  • メモリ不足やブラウザクラッシュが増えていないか
  • 他のCIジョブと同時実行したときに性能が崩れていないか

つまり、並列数は設定値ではなく運用値です。
マシンスペック、ブラウザ数、テストの重さに応じて調整し続けるべき項目です。

キャッシュ戦略で依存関係の準備時間を短縮する

CIで見逃されがちなのが、テスト本体ではなく準備時間です。
Playwrightの実行そのものより、依存関係のインストール、ブラウザバイナリの取得、ビルド生成、パッケージ解決に時間を使っているケースは少なくありません。
もし毎回ゼロから準備しているなら、テストコードをいくら改善しても、パイプライン全体の体感速度は思ったほど変わらないでしょう。
そこで重要になるのがキャッシュ戦略です。

キャッシュの本質は、再計算や再取得を避けることです。
Node.jsの依存関係、Playwrightブラウザ、ビルド成果物、パッケージマネージャのキャッシュなど、再利用可能なものは可能な限り活用すべきです。
ただし、何でも保存すればよいわけではありません。
キャッシュはヒット率が低ければ管理コストだけが増え、逆に古い状態を引きずって不整合の原因になることもあります。
したがって、保存対象と無効化条件を明確に設計する必要があります。

代表的な考え方は次の通りです。

対象 キャッシュの効果 注意点
パッケージ依存関係 install時間短縮 lockfile変化時の無効化
Playwrightブラウザ 初回ダウンロード削減 バージョン整合性の維持
ビルド成果物 再ビルド削減 変更範囲との整合性
テスト用データ 初期化短縮 鮮度と再現性の担保

重要なのは、どこに時間を使っているかを計測したうえでキャッシュ対象を決めることです。
インストールが数十秒しかかかっていないのに、複雑なキャッシュ設計へ時間を使うのは効率的ではありません。
逆に、毎回数分かかっているなら優先度は高い。
ここでも判断基準は印象ではなく実測です。

失敗時だけ詳細ログを残す運用で無駄を減らす

CIでは観測性も大切ですが、常に最大限の観測を行えばよいわけではありません。
trace、スクリーンショット、動画、詳細ログは原因調査に有効ですが、それらを毎回フル保存すると、ストレージ使用量やアップロード時間が増え、ジョブ全体の完了を遅らせることがあります。
特に成功ケースまで一律に詳細情報を残していると、大半は読まれないデータのために実行コストを払っている状態になりがちです。
情報取得の過剰投資です。

そのため、CIでは「失敗時だけ詳細を残す」運用が合理的です。
正常終了したテストには最小限の記録だけを残し、失敗時のみtraceや動画、追加ログを有効化する。
これにより、普段の速度を保ちながら、問題発生時の調査性も確保できます。
実運用におけるバランス設計です。

また、この考え方には副次的な利点もあります。
保存物が減ることで、必要なログを見つけやすくなります。
毎回大量の成果物が生成される環境では、読むべき情報の探索自体が負担になります。
失敗時に絞って記録することで、調査対象の密度が上がるわけです。
単なる軽量化ではなく、観測の質の向上でもあります。

見直しの観点としては、次のようなものがあります。

  • 成功時にも保存しているtraceや動画が本当に必要か
  • ログ量が多すぎて原因特定を逆に難しくしていないか
  • アップロードやアーティファクト保存がジョブ時間を圧迫していないか
  • 調査に必要な最低限の情報は失われていないか

CI環境でPlaywrightテストを安定かつ高速に回すには、単純にテストコードを速くするだけでは不十分です。
限られたCPUとメモリを前提に並列数を調整し、キャッシュ戦略で準備時間を削り、失敗時だけ詳細情報を残すことで観測コストを抑える。
こうした運用設計が、最終的な実行体験を大きく左右します。
CIはローカルの延長ではなく、制約つきの実行基盤です。
その前提を受け入れて設計すると、Playwrightはより安定して、しかも速く回るようになります。

高速化しても品質を落とさないための設計視点

テスト速度と品質を両立する設計方針を示すイメージ

Playwrightのテストを高速化するとき、最も注意すべきなのは、速度改善がそのまま品質改善を意味するわけではないという点です。
実行時間だけを指標にすると、見かけ上は速くなっても、テストとしての信頼性や保守性が落ちることがあります。
たとえば、待機を削りすぎて不安定になる、検証項目を減らして通りやすくする、複数ケースをまとめて件数を減らす。
どれも短期的には効果があるように見えますが、長期的には問題を抱えやすい設計です。
高速化の本来の目的は、雑に軽くすることではありません。
必要な品質を保ったまま、無駄なコストだけを削ることです。
ここを取り違えると、テストは速くても信用できないものになります。

E2Eテストは、ユニットテストよりも実行コストが高く、環境要因の影響も受けやすい領域です。
だからこそ、高速化の設計では、単に処理時間を減らすのではなく、どの品質を守るべきかを明確にしなければなりません。
速度、安定性、保守性。
この3つのバランスをどう取るかという視点が必要です。
ここに設計思想が表れます。

速いが壊れやすいテストを避ける考え方

高速化で最もありがちな失敗は、実行時間を削ることを優先しすぎて、テストが環境変化に弱くなることです。
たとえば、固定待機を一気に削除した結果、描画やAPI応答のわずかな揺らぎを吸収できなくなる。
あるいは、不要に思えた確認処理を外したことで、失敗原因の特定が難しくなる。
こうしたケースでは、平均実行時間だけを見れば改善しているかもしれません。
しかし、失敗率や再実行の手間まで含めて評価すれば、むしろ全体最適から遠ざかっている可能性があります。

壊れやすいテストには、いくつか共通した特徴があります。

  • 状態ではなく時間に依存している
  • DOM構造の細部に強く依存している
  • 一つのテストに確認事項を詰め込みすぎている
  • テスト対象と無関係な前提条件が多い
  • 失敗時に何が起きたか読み解きにくい

これらは速度とは直接関係ないように見えて、実は密接につながっています。
なぜなら、壊れやすいテストは再試行や調査コストを増やし、結果的にチーム全体の時間を奪うからです。
つまり、実行時間の短さだけでは速いテストとは言えません。
安定して意図通りに結果を返し、問題が起きたときに原因を追いやすいことまで含めて、初めて実用的に速いテストだと言えます。

ここで重要なのは、「最短で終わるテスト」と「最も効率がよいテスト」は同じではないという認識です。
前者は単発の秒数に注目していますが、後者は再現性や保守コストまで含めた全体の運用効率を見ています。
設計の視野の違いです。
E2Eテストでは、後者を選ぶべきです。

保守しやすいE2Eテスト構成を維持するコツ

高速化の効果を長持ちさせるには、保守しやすい構成を維持することが欠かせません。
どれだけ速いテストでも、少し画面が変わるたびに大量修正が必要なら、運用負荷は高くなります。
そして保守負荷が高いテストは、やがて手当てが後回しになり、不安定さや重複処理が再び増えていきます。
つまり、保守性の低さは将来的な性能劣化の入口でもあります。

保守しやすい構成を作るには、まず責務を分けることが重要です。
ログイン処理、画面遷移、データ準備、主要な操作、検証ロジックを無秩序に一つのテストへ詰め込むと、修正範囲が広がりやすくなります。
逆に、共通化すべき部分とケース固有の部分が整理されていれば、変更時の影響範囲を限定できます。
これは保守性だけでなく、無駄な再初期化を防ぐ意味でも有利です。

また、テスト構成では抽象化の粒度も重要です。
抽象化が浅すぎると重複が増え、深すぎると何をしているのか分かりにくくなります。
たとえば、共通処理を便利メソッド化しすぎて内部が巨大になると、速度改善どころかデバッグ性が下がることがあります。
必要なのは、読む人が前提条件と操作意図を追える程度の抽象化です。
過不足のない設計。
ここに保守しやすさがあります。

維持しやすい構成を考えるときは、次の観点が有効です。

観点 望ましい状態 避けたい状態
共通化 よく使う準備や操作だけ整理されている 何でも共通化して追跡不能
テスト粒度 1ケース1責務に近い 複数目的が混在している
セレクタ設計 意味のある属性や役割に依存 DOM構造や見た目に依存
データ準備 必要最小限で再利用可能 毎回フル初期化している

さらに、E2Eテストは増えることを前提に設計すべきです。
初期段階ではシンプルに見える構成も、テスト数が増えれば重複や依存が急速に目立ちます。
したがって、「今は困っていない」ではなく、「あと20件増えたときにも回るか」という視点で構成を見ておくと、将来的な崩れを防ぎやすくなります。
スケール前提の視点です。

高速化しても品質を落とさないためには、単に実行時間を縮めるのではなく、信頼性と保守性を含めた設計判断が必要です。
速いが壊れやすいテストは、短期的には魅力的でも、長期運用では必ず負債になります。
逆に、状態に基づいて待ち、責務を分け、変更に強い構成を保てば、テストは速さと品質を両立しやすくなります。
Playwrightの最適化で本当に目指すべきなのは、最速のテストではありません。
継続的に信頼でき、改善し続けられるテスト構成です。

Playwrightのテストが重い原因を特定して改善を継続するまとめ

Playwrightテスト高速化の要点を総括する記事まとめ用イメージ

Playwrightのテストが重くなる理由は、ひとつの要因で説明できるほど単純ではありません。
不要な待機、過剰なタイムアウト、ブラウザ起動の繰り返し、認証や初期化処理の重複、不安定なセレクタ、CI環境でのリソース競合。
こうした要素が少しずつ積み重なり、最終的に開発体験そのものを鈍らせます。
重要なのは、「Playwrightは重いものだ」と受け入れて終わらせないことです。
重さには必ず構造があり、その構造は観測と切り分けによってかなりの精度で把握できます。
つまり、重いという感覚を、改善可能な問題へ変換することが出発点です。

本記事で一貫して強調してきたのは、最適化を勘や経験則だけで進めないという姿勢です。
E2Eテストの高速化は、思いついた設定を試す作業ではありません。
まず全体時間と個別時間を切り分け、traceやreportやログから遅延箇所を確認し、CIとローカルの差も踏まえて、どの層に問題があるかを見極める必要があります。
この順番が大切です。
なぜなら、問題の所在が曖昧なまま対策を打つと、速度改善と引き換えに不安定さを増やしたり、本質ではない箇所へ時間をかけてしまったりするからです。
性能改善は、原因特定の質で成果が決まります。

また、改善対象は大きく三つに分かれます。
実行環境、設定、テストコードです。
実行環境では、特にCIにおけるCPUやメモリ制約、キャッシュの有無、アーティファクト保存コストが効いてきます。
設定では、workers、projects、retries、storageState、タイムアウトの調整が重要です。
そしてテストコードでは、waitForTimeout依存の回避、fixtureの再利用、重複した遷移や初期化の削減が、目に見える差を生みます。
つまり、高速化は一箇所の魔法の改善で実現するものではなく、複数レイヤーの小さな最適化を整合的に積み重ねることで成立します。
全体最適の発想です。

ここで忘れてはいけないのが、速さだけを目標にしないことです。
E2Eテストの価値は、短時間で終わることそれ自体にはありません。
信頼できる形で振る舞いを検証し、問題が起きたときに素早く原因へたどり着けることにあります。
したがって、高速化によって flaky test が増えたり、失敗時の観測性が落ちたり、保守性が悪化したりするなら、それは望ましい改善とは言えません。
速いが壊れやすいテストは、短期的には魅力的でも、長期的にはチームの負担になります。
速度、安定性、保守性のバランス。
この視点が極めて重要です。

改善を継続するうえでは、次のような進め方が現実的です。

  • まず遅いケースを計測し、全体傾向と個別傾向を分けて把握する
  • 実行環境、設定、テストコードのどこに主因があるかを切り分ける
  • 1回に1要素だけ変更し、改善効果と副作用を確認する
  • 実行時間だけでなく、失敗率と再現性も同時に見る
  • 改善を一度きりの施策で終わらせず、定期的に見直す

この「継続する」という点は特に重要です。
Playwrightのテストは、最初に最適化して終わりではありません。
アプリが成長すれば画面も増え、認証も複雑になり、データ準備も重くなります。
CIの構成が変わることもあれば、チームメンバーの実装方針によってテストコードの傾向が変わることもあります。
つまり、性能は静的な属性ではなく、運用の中で変化し続ける状態です。
だからこそ、定期的な計測と見直しを前提にした運用が必要になります。
改善を文化にできるかどうか。
ここが分かれ目です。

もし今、Playwrightのテストが重くてつらいと感じているなら、最初にやるべきことは大規模な書き換えではありません。
まずは、どのテストが、どの処理で、どの環境で遅いのかを明らかにすることです。
その上で、設定を見直し、共通化の粒度を整え、固定待機を減らし、不要な重複を削る。
こうした地道な改善を積み重ねることで、テストは確実に軽くなっていきます。
しかも、その過程でコードの見通しや保守性も向上しやすくなります。
単なる高速化ではなく、テスト基盤の健全化です。

結局のところ、Playwrightのパフォーマンス改善で本当に必要なのは、特別な裏技ではありません。
観測し、分解し、仮説を立て、小さく改善し、効果を確かめる。
その繰り返しです。
これはソフトウェア工学の基本であり、E2Eテストにもそのまま当てはまります。
重い原因を正しく特定できれば、改善は感覚的な努力ではなく、再現性のある技術的判断になります。
Playwrightのテスト運用を次の段階へ進めたいなら、速度の問題を単なる不満で終わらせず、設計と観測の対象として扱うことです。
そこから先に、持続的な高速化があります。

コメント

タイトルとURLをコピーしました