Gridを始める
クイックスタート
-
事前条件
- Java 11 もしくはそれ以上がインストールされていること
- ブラウザーがインストールされていること
- ブラウザードライバー
- Selenium 4.6 を使用していれば、Chrome, Firefox, Edge ドライバーが
PATH
から見つからない場合 Selenium Manager がドライバーを設定します。 PATH
が通っているインストール済みのもの
- Selenium 4.6 を使用していれば、Chrome, Firefox, Edge ドライバーが
- 最新の Selenium Server jar ファイルをダウンロードしていること
-
Grid の起動
java -jar selenium-server-<version>.jar standalone
-
あなたの WebDriver テストの対象を http://localhost:4444 に向ける
-
(必要があれば) ブラウザでhttp://localhost:4444を開いて実行中のテストや利用可能な capabilities を確認する。
さらにオプションを知りたい場合は以降のセクションに進んでください。
Grid コンポーネントロール
Grid は 6 つの異なるコンポーネントで構成され、様々な方法でデプロイすることができます。
必要に応じて、それぞれ個別に起動する(分散)か、ハブ&ノードのグループに分けるか、 全てを一つのマシンで起動する(スタンドアロン)かを選べます。
スタンドアロン
スタンドアロンは全ての Gridコンポーネントを 1 つに連結します。 スタンドアロンモードはシングルプロセスで動き、Grid の全機能を利用することができます。 スタンドアロンは単一のマシン上でのみ動かすことができます。
スタンドアロンは Selenium Grid を起動する最も簡単な方法でもあります。
デフォルトではサーバーはhttp://localhost:4444 で RemoteWebDriver
リクエストをリッスンします。
サーバーはデフォルトでシステムパス上の利用可能なドライバーを検出します。
java -jar selenium-server-<version>.jar standalone
スタンドアロンで Grid のを起動したら、WebDriver テストの対象をhttp://localhost:4444に向けてください。
スタンドアロンの一般的なユースケースは:
RemoteWebDriver
を使用したローカルでの開発やデバッグ- コードをプッシュする前の簡易なテスト実行
- CI/CD 向けの Grid のセットアップ(GitHub Actions, Jenkins など)
ハブ&ノード
ハブ&ノードは最も利用されているロールです。その理由は:
- 様々なマシンを Grid に統合できます
- 様々な OS やブラウザーバージョンを持つマシンなど
- WebDriver テストのエントリーポイントを持っています
- Grid を停止せずにキャパシティのスケールアップ・ダウンが可能です
ハブ
ハブは以下のコンポーネントで構成されています。 ルーター、ディストリビューター、セッションマップ、新規セッションキュー、イベントバス。
java -jar selenium-server-<version>.jar hub
デフォルトでは、サーバーはhttp://localhost:4444にて RemoteWebDriver
リクエストを待ち受けます。
ノード
ノードは起動時にシステムのパス が通っている利用可能なドライバーを検出します。
次のコマンドはノードがハブと同じマシン上で動作していることを前提としています。
java -jar selenium-server-<version>.jar node
同一マシン上での複数ノード
ノード 1
java -jar selenium-server-<version>.jar node --port 5555
ノード 2
java -jar selenium-server-<version>.jar node --port 6666
異なるマシンでノードとハブを動かす
ハブとノードは HTTP とイベントバスを介して通信します (イベントバスはハブの一部として存在します)。 ノードはイベントバスを通じてメッセージを送信し、登録処理を開始します。 ハブがメッセージを受け取り、ノードの存在を確かめるため HTTP を使ってノードにアクセスします。
ハブがデフォルトのポートを使用していれば、 --hub
フラグでノードを登録することができます。
java -jar selenium-server-<version>.jar node --hub http://<hub-ip>:4444
ハブがデフォルトのポートを使用していない場合、--publish-events
と --subscribe-events
のフラグが必要です。
例えばハブが 8886
8887
8888
ポートを利用している場合、
java -jar selenium-server-<version>.jar hub --publish-events tcp://<hub-ip>:8886 --subscribe-events tcp://<hub-ip>:8887 --port 8888
ノードはこれらのポートを登録する際に使用します。
java -jar selenium-server-<version>.jar node --publish-events tcp://<hub-ip>:8886 --subscribe-events tcp://<hub-ip>:8887
分散
分散 Grid を利用すると、各コンポーネントは別々に起動され異なるマシン上で動作します。
- イベントバスは Grid コンポーネント間での内部通信を可能にします。
デフォルトポートは 4442
, 4443
, 5557
です。
java -jar selenium-server-<version>.jar event-bus --publish-events tcp://<event-bus-ip>:4442 --subscribe-events tcp://<event-bus-ip>:4443 --port 5557
- 新規セッションキューは新規セッションリクエストをキューに積み、ディストリビューターがリクエストを取得できるようにします。
デフォルトポートは 5559
です。
java -jar selenium-server-<version>.jar sessionqueue --port 5559
- セッションマップはセッション ID とそのセッションが実行中のノードのマップを持ちます。
デフォルトのセッションマップのポートは 5556
です。
セッションマップはイベントバスと通信します。
java -jar selenium-server-<version>.jar sessions --publish-events tcp://<event-bus-ip>:4442 --subscribe-events tcp://<event-bus-ip>:4443 --port 5556
- ディストリビューターは新規セッションキューに新規セッションリクエストを問い合わせ、 capabilities がマッチするノードにアサインします。ノードは、ハブ&ノード構成の Grid におけるハブの登録と同じように、ディストリビューターに登録します。
デフォルトのディストリビューターのポートは 5553
です。
ディストリビューターは新規セッションキュー、セッションマップ、イベントバス、ノードと通信します。
java -jar selenium-server-<version>.jar distributor --publish-events tcp://<event-bus-ip>:4442 --subscribe-events tcp://<event-bus-ip>:4443 --sessions http://<sessions-ip>:5556 --sessionqueue http://<new-session-queue-ip>:5559 --port 5553 --bind-bus false
- ルーターは新規セッションリクエストをキューに、既存セッションのリクエストをそのセッションが実行中のノードに転送します。
デフォルトのルーターのポートは 4444
です。
ルーターは新規セッションキュー、セッションマップ、ディストリビューターと通信します。
java -jar selenium-server-<version>.jar router --sessions http://<sessions-ip>:5556 --distributor http://<distributor-ip>:5553 --sessionqueue http://<new-session-queue-ip>:5559 --port 4444
- ノード
デフォルトのノードのポートは 5555
です。
java -jar selenium-server-<version>.jar node --publish-events tcp://<event-bus-ip>:4442 --subscribe-events tcp://<event-bus-ip>:4443
テストメタデータ
テストにメタデータを追加して、GraphQL 経由で使用するか、Selenium Grid UI 経由でその一部( se:name
など) を可視化します。
メタデータは capability にse:
プリフィックスをつけることで追加できます。
Java での簡単な例を紹介します。
ChromeOptions chromeOptions = new ChromeOptions();
chromeOptions.setCapability("browserVersion", "100");
chromeOptions.setCapability("platformName", "Windows");
// Showing a test name instead of the session id in the Grid UI
chromeOptions.setCapability("se:name", "My simple test");
// Other type of metadata can be seen in the Grid UI by clicking on the
// session info or via GraphQL
chromeOptions.setCapability("se:sampleMetadata", "Sample metadata value");
WebDriver driver = new RemoteWebDriver(new URL("http://gridUrl:4444"), chromeOptions);
driver.get("http://www.google.com");
driver.quit();
Selenium Grid のクエリ
Grid 起動後、ステータスを問い合わせる方法は、 Grid UI と API 呼び出しの主に 2 通りあります。
Grid UI は、お好みのブラウザでhttp://localhost:4444 にアクセスすることで見られます。
API 呼び出しはhttp://localhost:4444/statusのエンドポイントか、 GraphQLが利用できます。
このページで紹介するコマンドの例は、わかりやすくするために コンポーネントがローカルで動作していると仮定しています。 より詳細な例と使用方法はコンポーネントの章を参照してください。
Java 11 の HTTP クライアントを利用する
デフォルトでは Grid はAsyncHttpClientを使用します。 AsyncHttpClient は Netty を使ったオープンソースのライブラリで、非同期での HTTP リクエストを実現します。 さらに WebSocket をサポートするため Grid に適しています。
しかし、AsyncHttpClient は 2021 年からあまり活発にメンテナンスされていません。 そして Java 11+ではビルトインの HTTP と WebSocket のクライアントを提供しています。 現在 Selenium はサポートする最小バージョンを Java11 にアップグレードする計画をしていますが、 それにはかなりの労力が必要です。メジャーリリースに合わせることはユーザー体験にとって重要です。
Java11 のクライアントを利用するにはselenium-http-jdk-client
jar ファイルをダウンロードし、
--ext
フラグで Grid の jar のクラスパスに通す必要があります。
jar ファイルはrepo1.maven.orgから直接ダウンロードできます。 Grid を起動する方法は以下の通りです:
java -Dwebdriver.http.factory=jdk-http-client -jar selenium-server-<version>.jar --ext selenium-http-jdk-client-<version>.jar standalone
selenium-http-jdk-client
をダウンロードする別の方法としてCoursierを使う方法があります。
java -Dwebdriver.http.factory=jdk-http-client -jar selenium-server-<version>.jar --ext $(coursier fetch -p org.seleniumhq.selenium:selenium-http-jdk-client:<version>) standalone
ハブ&ノードか分散モードで動かす場合、-Dwebdriver.http.factory=jdk-http-client
と
--ext
フラグの設定が各コンポーネントに必要になります。
Grid サイズ
Grid ロールの選択は、どのような OS やブラウザをサポートする必要があるかによって決まります。 どの OS、ブラウザをサポートするか、どのくらいの並列セッションを実行するか、マシンの数とそれらの性能(CPU、RAM)に依存します。
セッションを並列で作成するのは、ディストリビューターが利用可能なプロセッサーに依存します。たとえば、 マシンに 4 つの CPU がある場合、ディストリビューターは同時に最大 4 つのセッションしか作成できません。
デフォルトでは、ノードがサポートする同時セッションの最大数は、利用可能な CPU の数によって制限されます。 たとえば、ノードのマシンに 8CPU がある場合、同時に最大 8 つのブラウザセッションを実行できます(ただし、Safari は常に 1 つです)。 また各ブラウザセッションは約 1GB の RAM を使用することが期待されます。
一般的にノードはできるだけ小さくすることが推奨されます。32CPU と 32GB の RAM を持つマシンで 32 の同時ブラウザセッションを実行するよりも、 32 の小さな プロセスをよりよく分離するために、 32 の小さなノードを持つことが推奨されます。これによって、もしノードに障害が発生しても、分離されて処理されます。 Docker はこの方法を実現するための優れたツールです。
デフォルト値(ブラウザあたり 1CPU/1GB RAM)は推奨値であり、あなたの用途に沿わない可能性があることに注意してください。 この値は参考値としての推奨であり、継続的にパフォーマンスを測定することで、あなたの環境にとって理想的な値を見つけることができるでしょう。
Grid のサイズは、サポートされる同時セッションの数と、ノードの数に関連しており、 万能なサイズというものはありません。以下のサイズは概算で、環境が違えば変わる可能性があります。 例えば、120 台のノードを持つハブ&ノードの場合、ハブが十分なリソースを持っていればうまく機能するかもしれません。 また、この数値は確定したものではありません。フィードバックをお待ちしています。
Small
5 台以下のノードで、スタンドアロンかハブ&ノード
Middle
6〜60 台のノードで、ハブ&ノード
Large
60〜100 台のノードで、ハブ&ノード、あるいは 100 台以上のノードで分散
警告
Grid を保護しないと、以下のような問題が発生する可能性があります。
- Grid インフラストラクチャへのオープンアクセスを許容してしまう。
- サードパーティが内部 Web アプリケーションやファイルにアクセスすることを許可してしまう。
- サードパーティにカスタムバイナリの実行を許可してしまう。
Detectify のブログで公開されてしまった Grid が どのように悪用されるかを紹介しています: Don’t Leave your Grid Wide Open
参考文献
- Components: 内部のコンポーネントの仕組みを知る
- Configuration: Grid の設定をカスタマイズする
- Architecture: Grid のコンセプトを理解する
- Advanced Features: Grid のさらなる可能性を探る