Docker ComposeでSelenium Gridを構築:並列テストを「爆速」にするソリューション

Docker tutorial - IT technology blog
Docker tutorial - IT technology blog

逐次テストの苦悩と、Selenium Gridという名の救世主

自動テストを始めたばかりの頃、私はスクリプトを自分のPCで直接実行していました。テストケースが300件に達するまでは順調でしたが、リグレッションテストのたびに2時間以上かかるようになり、結果を待つのはまさに苦行でした。さらに、Chrome、Firefox、Edge用の各種ドライバーをインストールすることで、PCの設定が「ゴミ溜め」のようになってしまいました。

そこで救世主として現れたのがSelenium Gridです。これは、テストシナリオを複数のマシン(Node)に分散して同時実行することを可能にします。しかし、従来の.jarファイルとJavaの手動設定によるインストールは非常に時間がかかります。Nodeを追加したりブラウザのバージョンを更新したりするたびに、最初から設定をやり直す必要がありました。

6ヶ月間の実運用を経て、私はDocker ComposeとSelenium Gridを組み合わせるのが最適解であると確信しました。コマンド一つで、マルチブラウザ対応のテスト実行システム全体を構築できます。以下に、チームのパフォーマンスを最適化するために私が適用したプロセスを紹介します。

環境準備

始める前に、マシンに以下の2つの基本的なツールがインストールされている必要があります。

  • Docker Desktop (Windows/Mac) または Docker Engine (Linux)
  • Docker Compose (通常、Dockerのインストールパッケージに含まれています)

ターミナルを開き、以下のコマンドで素早く確認してください:

docker --version
docker-compose --version

最適化されたdocker-compose.ymlの作成

個別のコンテナをバラバラに管理するのではなく、Docker Composeを使ってすべてを一つにまとめます。プロジェクトディレクトリを作成し、その中に以下の内容でdocker-compose.ymlファイルを作成します。

version: "3.8"
services:
  selenium-hub:
    image: selenium/hub:4.15.0
    container_name: selenium-hub
    ports:
      - "4444:4444"
    environment:
      - GRID_MAX_SESSION=16
      - GRID_BROWSER_TIMEOUT=300

  chrome:
    image: selenium/node-chrome:4.15.0
    shm_size: 2gb
    depends_on:
      - selenium-hub
    environment:
      - SE_EVENT_BUS_HOST=selenium-hub
      - SE_EVENT_BUS_PUBLISH_PORT=4442
      - SE_EVENT_BUS_SUBSCRIBE_PORT=4443
      - SE_NODE_MAX_SESSIONS=4

  firefox:
    image: selenium/node-firefox:4.15.0
    shm_size: 2gb
    depends_on:
      - selenium-hub
    environment:
      - SE_EVENT_BUS_HOST=selenium-hub
      - SE_EVENT_BUS_PUBLISH_PORT=4442
      - SE_EVENT_BUS_SUBSCRIBE_PORT=4443
      - SE_NODE_MAX_SESSIONS=4

見逃せない技術的な注意点

  • shm_size: 2gb: これは極めて重要なポイントです。Dockerのデフォルトでは共有メモリ(/dev/shm)に64MBしか割り当てられず、重いページを読み込む際にChromeが非常にクラッシュしやすくなります。ブラウザをスムーズに動作させるために、少なくとも2GBまで増やしましょう。
  • SE_NODE_MAX_SESSIONS: このパラメータは、1つのNodeで同時に実行するブラウザの数を決定します。パフォーマンスとRAMリソースのバランスを考慮し、私は通常4に設定しています。
  • selenium-hub: 司令塔の役割を果たし、スクリプトを受け取って空いているNodeに割り当てます。

設定の過程で、YAMLファイルやHubからのJSONログを再確認する必要がある場合は、Toolcraft of JSON Formatterを使用できます。このツールは生データを非常に素早く整形してくれるため、目視でコードを確認するよりも大幅に時間を短縮できます。

起動と成果の確認

ファイルのあるディレクトリで、以下のコマンドを実行します:

docker-compose up -d

Dockerがイメージのプルを完了したら、http://localhost:4444にアクセスしてください。Selenium Grid Consoleのインターフェースが表示され、準備が整ったChromeとFirefoxのNodeリストが確認できるはずです。

Dockerの最大の強みはスケーラビリティ(拡張性)です。4つではなく10個のChromeスレッドを実行する必要がある場合は、次のように入力するだけです:

docker-compose up -d --scale chrome=3

設定コードを一行も修正することなく、10秒足らずでシステムが自動的に新しいコンテナを複製します。

テストスクリプトをGridに接続する

ローカルでドライバーを初期化する代わりに、スクリプトの接続先をHubに向けます。以下はPythonの例です:

from selenium import webdriver

options = webdriver.ChromeOptions()
# ポート4444で動作中のHubに接続
driver = webdriver.Remote(
    command_executor='http://localhost:4444/wd/hub',
    options=options
)

try:
    driver.get("https://itfromzero.com")
    print(f"ページタイトル: {driver.title}")
finally:
    driver.quit()

6ヶ月間の運用で得た実戦的な教訓

このGridクラスターを毎晩のリグレッションテストに適用した結果、3つの貴重な経験則を得ました:

  1. RAMの管理: ブラウザはリソースを大量に消費します。4つのChromeセッションを実行する1つのNodeには、途中でフリーズしないために実質2GBから3GBのRAMが必要です。
  2. 「ゾンビ」セッションの掃除: 常にGRID_BROWSER_TIMEOUTを設定してください。スクリプトがクラッシュしてdriver.quit()を呼び出せなかった場合でも、Hubが一定時間後に自動的にブラウザを解放してくれます。
  3. 実際の速度: Gridで8スレッドの並列実行に切り替えた後、チームの300件のテストケースは120分からわずか18分に短縮されました。

Selenium GridにDocker Composeを使用することは、テストの高速化だけでなく、開発者のマシンからCI/CDサーバーまで同一の環境を保証することにも繋がります。皆さんもぜひ、ご自身のオートメーションシステムの最適化に挑戦してみてください!

Share: