Selenium 4のリリースとともに、
Selenium Grid(以下Grid)もver4にメジャーアップデートされたので新機能を試してみました。
Selenium Gridとは
Selenium Grid allows the execution of WebDriver scripts on remote machines (virtual or real) by routing commands sent by the client to remote browser instances. It aims to provide an easy way to run tests in parallel on multiple machines.
GridはWebDriverスクリプトの実行リクエストを、接続されたクライアント上のブラウザインスタンスに振り分けてくれるサーバです。ロードバランサのイメージが分かりやすいかと思います。主にはテストの並列実行などに使います。
Dynamic Gridとは
Grid 4 has the ability to start Docker containers on demand, this means that it starts a Docker container in the background for each new session request, the test gets executed there, and when the test completes, the container gets thrown away.
Dynamic Gridはリクエストに応じて対応するブラウザコンテナを自動で立ち上げる機能です。
Grid 3まではブラウザが起動できるノードを事前に接続しておくことが必須でしたが、Grid 4からはその手間が不要になるということですね。すごE。
やってみる
ということで早速やってみます。
環境
- macOS Big Sur 11.3.1
- Docker関係
- Docker Desktop 4.1.1
- socat 1.7.4.1
- Docker用のTCPプロキシを立てるのに使います
- テストスクリプト関係
- Python 3.9
- selenium 4.0.0
- pytest 6.2.4
- pytest-xdist 2.4.0
- テストの並列実行に使います
- Python 3.9
1. 必要なファイルをDLする
筆者のリポジトリに必要ファイルをまとめてあるのでcloneしてきてください。
なお、以下の2ファイルはSeleniumHQ/docker-seleniumから拝借しています。必要に応じてアップデートしてください。
2. (macOSのみ) socatでTCPプロキシサーバを立てる
macOSの場合はnodes/config-docker.toml
のコメントに従い、
以下のコマンドでDockerがTCP通信ができるようにプロキシサーバを立てます。
socat -4 TCP-LISTEN:2375,fork UNIX-CONNECT:/var/run/docker.sock
3. docker composeでSelenium Gridを起動する
cloneしてきたディレクトリ直下で以下のコマンドを実行し、Gridサーバを立てます。
docker-compose -f docker-compose-v3-dynamic-grid.yml up
以下のログが表示されていれば起動に成功しています。
segrid4-node-docker-1 | 07:30:54.734 INFO [NodeServer.lambda$createHandlers$2] - Node has been added
selenium-hub | 07:30:54.739 INFO [GridModel.setAvailability] - Switching node a3ff3d19-5809-4192-aae9-fb031183d006 (uri: ***) from DOWN to UP
この状態で http://localhost:4444/ にアクセスしてみましょう。
以下の画像のようにDockerノードが接続されているのが確認できると思います。
4. pytest-xdistでテストを並列実行する
このノードはChrome, Firefox, Edgeのブラウザコンテナをオンデマンドに展開できます。
ということで、各ブラウザで http://whatsmyuseragent.org/ にアクセスしてスクショを撮る簡単なスクリプトを書いてみました。
from selenium import webdriver
class TestGrid:
def choose_driver(self, browser: str) -> webdriver:
command_executor = "http://localhost:4444"
if browser == "firefox":
options = webdriver.FirefoxOptions()
elif browser == "edge":
options = webdriver.edge.options.Options()
else: # chrome
options = webdriver.ChromeOptions()
options.set_capability("se:recordVideo", "true")
options.set_capability("se:timeZone", "JST")
driver = webdriver.Remote(
command_executor=command_executor,
options=options,
)
driver.set_window_size(1024, 768)
return driver
def test_chrome(self):
driver = self.choose_driver("chrome")
driver.get('http://whatsmyuseragent.org/')
driver.save_screenshot("./results/google.png")
driver.quit()
assert True
def test_firefox(self):
driver = self.choose_driver("firefox")
driver.get('http://whatsmyuseragent.org/')
driver.save_screenshot("./results/firefox.png")
driver.quit()
assert True
def test_edge(self):
driver = self.choose_driver("edge")
driver.get('http://whatsmyuseragent.org/')
driver.save_screenshot("./results/edge.png")
driver.quit()
assert True
この各テストメソッドを並列実行してみます。
pytestでテストを並列実行するにはpytest-xdistプラグインをインストールした上で、以下のようにコマンドを実行すればOKです。
pytest -n 3 tests/
http://localhost:4444/ のサイドバーよりSessionsを確認してみると、3コンテナが同時に動いていることが確認できます。
各セッションのビデオアイコンをクリックするとコンテナにVNC接続をすることができます。
パスワードはsecret
です。
実行が完了しresults/
に各ブラウザで撮影したスクリーンショットが保存されていればデモは成功です!
参考 : Video Recording
ちなみに上記スクリプトではもう一つの新機能、Video Recordingも利用しています。
これはその名の通りテスト時の動画を録画する機能です。
choose_driverメソッドに記載の以下の一文でVideo Recordingを有効化しています。
options.set_capability("se:recordVideo", "true")
動画はassets/
以下に保存されているので確認してみてください。
余談 : 進化しすぎて手に負えないGrid 4
本記事ではSelenium Grid 4の新機能であるDynamic Gridを試しました。
が、もっと根本的なところとして、Grid 4ではGridの構成要素が変わっていたりと内部的に大きな変更が入っている模様です。
大規模分散型システムに向けた変更だと思いますが、現状そこまでの大規模分散型システムを作る機会がないので詳しくは調査していません。悪しからず。
ご興味のある方は下記記事が参考になるかと思います。