QR Send

スマホとPCのChrome間で、URLやテキストをQRコード1回のペアリングで送り合える自作Chrome拡張。アカウント不要・無料。

使ってみる →

Selenium(Ruby)からPlaywright(TypeScript)へ移行して変わった考え方

Selenium・自動化

なぜ移行を検討し始めたか

長らくRubyのSeleniumでUI自動化を書いてきたが、最近はPlaywright(TypeScript)を試す機会が増えている。きっかけは単一の不満というより、いくつかの小さな引っかかりの積み重ねだった。要素が見つかるまでの待機処理を自分であちこちに書く必要があること、複数のブラウザ状態を並行して扱うテストがドライバのインスタンス管理で煩雑になりがちなこと、そして失敗したときにトレースやスクリーンショットを自分で仕込まないと「どこで何が起きたか」が追いにくいことだ。

どれも致命的な欠陥ではなく、書き方を工夫すれば解決できる話ではある。ただPlaywrightではこれらの多くが最初から仕組みとして用意されており、自分でラップする量が減る。移行するかどうかより先に、まず「発想がどう変わるか」を整理しておきたい。

「待つコードを書く」から「アクションが自動で待つ」へ

Seleniumでは、要素の出現やクリック可能な状態を待つコードを明示的に書く必要がある。これを省くと、ページ描画の途中で要素を掴みに行ってしまい、意図しないタイミングでの失敗が起きる。

wait = Selenium::WebDriver::Wait.new(timeout: 10)
wait.until { driver.find_element(id: "submit").displayed? }
driver.find_element(id: "submit").click

Playwrightでは、クリックなどのアクション自体が「要素が操作可能な状態になるまで自動で待つ」ようになっている。呼び出す側が待機の存在を意識しなくてよい。

await page.getByRole("button", { name: "送信" }).click();

この違いは単なる行数の差ではなく、「待つ責任がどこにあるか」という設計思想の違いだと感じる。Seleniumでは待つ責任は呼び出し側にあり、Playwrightではアクション自体にある。

ロケータは「今すぐ探す」ものではなく「使うときに解決する」もの

Seleniumのfind_elementは呼んだ瞬間にDOM検索を実行する。要素がまだ描画されていなければ、その場で例外になる。

element = driver.find_element(css: ".item-row")
# ここで即座にDOM検索が実行される。未描画なら例外

Playwrightのlocatorは検索条件を保持するだけのオブジェクトで、実際の検索はclicktextContentなど何らかの操作を行うタイミングまで遅延される。

const row = page.locator(".item-row");
// この時点では検索されない。操作時に評価される
await row.click();

この遅延評価のおかげで、「要素が後から動的に生まれるかもしれない」ことを前提にしたコードが自然に書ける。Seleniumでは「まだ無いかもしれないから待つ」というコードが必要だったところが、Playwrightでは「参照だけ先に持っておく」という感覚に置き換わる。

ブラウザコンテキストの分離という発想

複数ユーザーの状態を同時に扱うテストをSeleniumで書く場合、実質的にドライバのインスタンスをユーザーごとに立ち上げることになる。

driver_a = Selenium::WebDriver.for(:chrome, options: build_options(profile: "user_a"))
driver_b = Selenium::WebDriver.for(:chrome, options: build_options(profile: "user_b"))

Playwrightにはブラウザプロセス1つの中に、Cookieやストレージが独立した「コンテキスト」を複数持てる仕組みがある。

const browser = await chromium.launch();
const contextA = await browser.newContext();
const contextB = await browser.newContext();
const pageA = await contextA.newPage();
const pageB = await contextB.newPage();

ブラウザプロセスの起動コストを払わずに、独立したセッションを何個も持てるのは体感の差が大きい。並行テストやログイン状態違いの検証を書くときの心理的なハードルが下がった。

それでもSeleniumが優位な場面

公平に見て、Seleniumには今でも分がある。対応言語がJava・Python・Ruby・C#など幅広く、既存の言語資産やチームのスキルセットに合わせやすい。歴史が長い分、枯れた情報や過去のトラブル事例が豊富で、niche なブラウザやレガシー環境への対応実績もある。すでにRubyの資産で固めた自動化基盤があるなら、それを丸ごと置き換える理由には乏しい。Playwrightの利点は主にChromium系ブラウザでの開発体験に集中しており、対応ブラウザの幅そのものはSeleniumの方が依然として広い。

移行は全部やらず、新規から始めるのが現実的

既存のSeleniumコードをすべてPlaywrightに書き換えるのは、費用対効果が見合わないことが多い。動いているものを壊すリスクの方が大きい。現実的なのは、新規に書くテストや自動化スクリプトからPlaywrightを採用し、既存資産はSeleniumのまま維持するという併存路線だ。両者は対象がブラウザ操作という点で共通しているため、チーム内で並行して学習コストを払っても無理がない。

まとめ

  • Seleniumは「待つコードを自分で書く」、Playwrightは「アクションが自動で待つ」という責任の置き場所の違いがある
  • ロケータはSeleniumが即時評価、Playwrightは遅延評価という違いがあり、動的なDOMへの向き合い方が変わる
  • Playwrightのブラウザコンテキストは、プロセスを増やさずに独立したセッションを複数持てる
  • 対応言語の幅や枯れた実績ではSeleniumに分があり、既存のRuby資産を無理に置き換える必要はない
  • 移行は全置き換えではなく、新規のテスト・自動化からPlaywrightを採用する併存路線が現実的

コメント

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