自動化エンジニアのキャリアには、それがコーディングというより「悪魔祓い(エクソシズム)」のように感じる瞬間が必ずあります。午前2時、パイプラインの失敗ログを睨みつける。エラーには ElementNotInteractableException とあるのに、スクリーンショットにはボタンがはっきりと写っている。亡霊に憑りつかれているような気分です。
私たち全員が通った道です。最初は価格のスクレイピングやログインフォームのテストといった簡単なスクリプトから始まります。しかし半年後には、風が吹くだけで失敗するような、脆く巨大なテストスイートの保守に追われているのです。ツールの選択は重要です。それは単に構文の違いの問題ではなく、正気を保てるかどうかの問題だからです。
ブラウザ自動化のランドスケープは、私たちの足元で大きくシフトしました。かつてSeleniumが独占していた市場は、古参の勢力と、新しいNode.jsネイティブの重量級プレイヤーであるPuppeteerやPlaywrightとの覇権争いへと分裂しました。これは単なるライブラリ選びではありません。私たちがWebとどう対話するかという「哲学」の選択なのです。
なぜ今、Seleniumの話をするのか?
2024年にもなってSeleniumを批判するのは、ある種「流行り」のようなものです。SeleniumはjQueryよりも古い技術です。WebDriverプロトコルに依存しており、コードとブラウザの間に仲介役を挟むことで、どうしてもレイテンシー(遅延)が発生します。しかし、Seleniumを完全に否定するのは初心者の過ちです。
エコシステムという「壕(ほり)」
Seleniumの最大の資産は、その圧倒的で頑固なまでの「偏在性」です。もし組織内でJava、C#、Python、Ruby、JavaScriptを使ってバインディングを書く必要があるなら、Seleniumは部屋にいる唯一の「大人」の選択肢となることがよくあります。
「標準化」が至上命題であるエンタープライズ環境において、Seleniumは既存のCI/CDアーキテクチャのパターンにぴったりとハマります。エコシステムは巨大です。もしエッジケースに遭遇したとしても――例えばレガシーな銀行アプリで不明瞭なiframeの挙動を扱う場合など――StackOverflowには2013年に誰かが解決したログが残っているはずです。
しかし、そのアーキテクチャは老朽化しています。Seleniumはドライバサーバー(chromedriver, geckodriver)にHTTPリクエストを送り、それがブラウザのアクションに変換される仕組みであるため、本質的に非同期であり、それが「不安定さ(Flakiness)」につながります。Seleniumのコードベースで見られる sleep コマンドの使用は、多くの場合、レースコンディション(競合状態)に対する敗北宣言です。
「古参」を使い続けるべき場合
言語の制約: チームが厳格なJavaまたはC#の現場である場合。
実機テスト: 幅広いモバイル実機サポートや、奇妙なレガシーブラウザ(IE11など)のバージョン対応が必要な場合。
Gridインフラ: 既に正常に稼働している巨大なSelenium Gridへの投資がある場合。
Puppeteer: Chrome DevTools Protocol (CDP) 革命
GoogleがPuppeteerをリリースしたとき、それは単なるライブラリの公開ではなく、パラダイムシフトでした。WebDriverのおしゃべりなHTTP通信の代わりに、Puppeteerは Chrome DevTools Protocol (CDP) を使用してブラウザと直接WebSocket接続を開通させたのです。
CDPの威力
これは業界にとって「アハ体験」の瞬間でした。突然、私たちは単にボタンをクリックするだけでなく、ブラウザの「脳内」に入り込んだのです。
ネットワークの傍受: リクエストの一時停止、ヘッダーの修正、モックレスポンスの注入、そして続行――これらすべてがネイティブに行えます。
パフォーマンス指標: Performance APIへのアクセスはもはやハックではなく、単なる関数呼び出しになりました。
信頼性: 通信は双方向かつイベント駆動型であるため、要素が出現するまでDOMをポーリング(監視)することに関連する「不安定さ」はほぼ消滅しました。
Puppeteerは洗練され、軽量で、焦点が絞られています。Seleniumという「スイスアーミーナイフ」に比べれば、「外科医のメス」のような感覚です。しかし、その焦点の絞り込みは制限でもあります。基本的にChrome中心のツールだからです(Firefoxのサポートも存在しますが、常に二級市民のような扱いを受けてきました)。
Node.jsへの偏り
Puppeteerは、悪びれることなくJavaScript/TypeScript向けです。これはPythonを使うデータサイエンス勢やJavaを使うエンタープライズ勢を遠ざけますが、ReactやVueアプリを構築する現代のWeb開発者にとっては、シームレスな開発者体験(DX)を生み出します。JSでアプリを書き、JSでテストするのです。
Playwright: 新たな王者の誕生か?
Puppeteerが革命だったとすれば、Playwrightはその革命を飲み込んだ「進化」です。Microsoftによって(皮肉なことに、Googleで元々Puppeteerを作ったのと同じチームによって)作成されたPlaywrightは、CDPの概念を取り入れ、その最大の欠陥を修正しました。
「Auto-Wait(自動待機)」の哲学
Playwrightが導入した最も価値のある機能は Auto-Waiting です。Seleniumでは wait.until(element_is_visible) と書きます。Playwrightでは、単にクリックするだけです。エンジンは自動的に要素がDOMにアタッチされ、可視化され、安定しており(アニメーション中でない)、有効であることを確認し、アクションを実行する前にこれらのチェックがパスするのを待ちます。これにより、安定したテストを書くために必要なコード量が劇的に削減されます。
真のクロスブラウザサポート
PlaywrightはChromeだけで止まりませんでした。WebKit(Safari)とFirefoxエンジンにパッチを当て、同じプロトコルを話せるようにしました。これにより、異なるドライバを管理する悪夢を見ることなく、単一のコマンドで3つの主要なレンダリングエンジンすべてでテストを実行できます。
コンテキストと分離(アイソレーション)
Playwrightは Browser Contexts という概念を導入しました。コンテキストはシークレットウィンドウのようなもので、作成と破棄が高速(ミリ秒単位)です。
並列化: 1つのブラウザインスタンスを立ち上げ、20の並列コンテキストでテストを実行できます。これは10年もの間Selenium Gridを悩ませてきた速度のボトルネックを解消します。
状態管理: ストレージの状態(Cookie、ローカルストレージ)をコンテキストに即座に注入でき、テストのたびにUI経由でログインする必要を回避できます。
武器の選び方:戦略フレームワーク
どう選ぶべきでしょうか? GitHubのスター数を見るのではなく、チームの制約を見てください。スコープ(Scope)、速度(Speed)、**スタック(Stack)**の3つの柱に基づいて、シンプルな意思決定マトリックスに分解できます。
- スコープの柱
実際に何をテストしていますか?
広範な互換性: 要件定義書に「Safari、Firefox、Chromeでの機能を保証すること」とあるなら、Playwrightが明確な勝者です。そのWebKitの実装は、PuppeteerをChrome以外のブラウザとうまく連携させようとするよりも遥かに優れています。
レガシーエンタープライズ: Internet Explorerへの厳格な準拠や、特定の奇妙なドライバ構成を必要とする社内ERPシステムをテストしているなら、依然としてSeleniumが最も安全な賭けです。
2. 速度の柱
スクレイピング: 主な目的が大規模なデータ抽出である場合、Puppeteerの方が軽量なことが多いです。しかし、シンプルなAPI呼び出しでリソース(画像やCSSなど)をブロックできるPlaywrightの機能は、スクレイピングの速度においても強力な競争相手となります。
CIパイプライン: Playwrightのシャーディング(分割実行)と並列実行機能は、箱から出してすぐに使える点で優れています。もしテストスイートに4時間かかっているなら、Playwrightへ移行することで、複雑なインフラ変更なしに20分に短縮できる可能性があります。
3. スタックの柱
チームの専門知識: Puppeteerを使うためだけに、Python開発者にJavaScriptを書くことを強制してはいけません。PlaywrightはPython、C#、Java用のネイティブバインディングを提供しています。多言語(ポリグロット)な組織にとって、これはPuppeteerに対する巨大な戦略的アドバンテージです。
ステップ・バイ・ステップガイド:移行の評価
さて、あなたは乗り換えを検討しています。すべてを書き直してはいけません。以下のチェックリストに従って、移行のROI(投資対効果)を検証してください。
ステップ 1:「不安定な5つ(The Flaky 5)」の監査
現在のスイートの中で、最も頻繁に失敗する5つの独立したテストを特定してください。これらは通常、ポップアップ、動的なロード、または重いJavaScript実行を含む複雑なフローです。
ステップ 2:POCの実装
その5つのテストだけをPlaywright(またはPuppeteer)で書き直してください。完璧を目指さず、同等性を目指してください。待機ロジック(Wait logic)を処理するのに必要なコード行数がどれだけ減ったかに注目してください。ボイラープレートコードの削減は、通常、移行に関する最も強力な論拠となります。
ステップ 3:シャドウ実行(The Shadow Run)
CIを設定して、既存のSeleniumスイートと一緒に新しいヘッドレススクリプトを実行してください。まだビルドをブロックしてはいけません。ただ観察するのです。2週間にわたって実行時間と安定性を比較してください。
ステップ 4:セレクタの現実チェック
セレクタを分析してください。Playwrightは、脆いXPathよりも、ユーザー向けのセレクタ(例:getByRole('button', { name: 'Submit' }))を推奨しています。アプリケーションにアクセシビリティ属性が欠けている場合、Playwrightの最良のロケータを活用できないため、移行は苦痛になるかもしれません。
ステップ 5:ブラウザコンテキスト戦略
Playwrightに移行する場合、storageState をどう使うか計画してください。認証状態を保存し、テスト間で再利用することで、UIログインをスキップできれば、テスト実行時間の30〜40%削減がすぐに見込めます。
最後に:避けられないシフト
私たちは「外部ドライバとしての自動化」から「内部プロセスとしての自動化」へと移行しつつあります。
Seleniumは、私たちがブラウザについてどう考えるかを標準化することで、大いに役立ちました。Puppeteerは、エンジンと直接対話することでより速くなれることを示しました。そしてPlaywrightは、そのスピードを取り入れ、現代のWeb開発の厄介な現実を認識した開発者体験(DX)でそれを包み込みました。
厳格な「Java + Selenium」の現場にとって不都合な真実は、業界が「言語のバインディング」よりも「ブラウザのネイティブ機能」を優先するツールへと動いているということです。
もし今日新しいプロジェクトを始めるなら、Webテストのデフォルトの選択肢はPlaywrightであるべきです。それはSeleniumの多言語サポートと、Puppeteerのアーキテクチャを兼ね備えています。単にスピードだけの話ではありません。保守コストの話です。StaleElementReferenceException のデバッグに費やさない時間は、プロダクトを実際に構築するために使える時間なのです。
とはいえ、単にチェックボックスを埋めるためだけに移行してはいけません。もしあなたのSeleniumスイートが安定しており、十分に高速で、チームがそれを熟知しているなら、それを書き直すコストは「技術的負債」に変装した何かです。最高のツールとは常に、夜中にポケベル(やSlack通知)で叩き起こされることなく、チームがぐっすり眠れるツールのことです。