この記事はSelenium/Appium Advent Calendar 2017の第18日目です。
SWETのGLやってます@okitanです。
少し前ですが、「日本Seleniumユーザーコミュニティ」のエキスパートが教えるSelenium最新事情という連載にDockerでSelenium Gridを構築して複数マシンのブラウザ自動テストを行うという記事を書きました。 記事中では、公式のSelenium GridのDockerイメージを使う方法に加えて、現在SWETで注目して運用しているZaleniumを利用する方法を紹介しました。
本記事では、Kubernetesを利用し、Zaleniumの以下の2つの構築方法を紹介します。
- 個人の開発環境のminikube上で構築する
- Google Kubernetes Engine(GKE)に構築する
なお、本記事ではKubernetesに関する用語が出て来ます。 KubernetesのドキュメントやWEB+DB PRESS Vol.99の「実践Kubernetes」がわかりやすいと思います。
脱線しますが、WEB+DB PRESS Vol.99には、SWETの@tarappoが寄稿した「UIテスト自動化」も特集2として載ってますのでおすすめです。
Selenium GridとZaleniumについてのおさらい
Zaleniumは複数のマシンで分散してブラウザ操作の自動化を実現するSelenium Gridを構築するためのソフトウェアです。 Selenium Gridを利用するとGoogle Chrome・Firefox・Microsoft Edge等多種多様なブラウザを管理でき、クロスブラウザテスティングが簡単にできるようになります。 Zaleniumは公式のSelenium Gridに追加で以下の機能をもっています。 (Selenium Gridに関する詳細やZaleniumの機能の詳細については、元記事を読んでください)
- Selenium nodeのオートスケール機能
- ブラウザの動作をSelenium Gridの管理コンソール上からのライブで確認できる機能(ライブプレビュー)
- ブラウザ動作の録画機能
- 録画された動画をドライバのログと合わせてWeb上で一覧できるダッシュボードという機能があります
ここで注目したいのは、Selenium nodeのオートスケール機能です。自動テストを開発プロセスに組み込むにはある程度短い時間で開発に対してフィードバックを行う必要があります。 その上、自動テスト数が増えていくにしたがって増加する実行時間を短くするため、並列実行数を増やしていかないといけません。 そのために、実行時間が何分以内に収まるような自動テストの並列実行計画の戦略と、それを受け入れるだけのキャパシティのあるテスト実行環境が必要になります。 Zaleniumのオートスケール機能はこの後者の問題を解決してくれます。
そしてオートスケールと相性の良いのがクラウドです。 今日ではKubernetesを用いてクラウドでコンテナ群を管理するのが一般的です。 もちろん、ZaleniumもKubernetesに対応しています。 また、最終的にクラウドで動かすにしてもローカルで動作確認できると便利なので、自分の開発環境で試してみる用にminikubeでの説明もあわせておこないます。
なお、以下の環境で動作確認してます。
- macOS El Capitan 0.11.6
- Docker for Mac 17.09.1-ce-mac42
- minikube 0.24.1
- kubernetes-cli 1.8.5
- docker-machine-driver-hyperkit
- dosel/zalenium 3.8.1c
- elgalu/selenium 3.8.1-p3
- Ruby 2.4.1p111
- selenium-webdriver 3.8.0
minikube上にZaleniumを立てる
事前準備
minikubeのインストール方法を簡単に説明します。 公式のminikubeのチュートリアルは、 deprecatedとなっているdocker-machine-driver-xhyveを利用しています。 本記事ではdocker-machine-driver-xhyveの代替となるHyperkit driverのインストール方法もあわせて紹介しておきます。
Homebrew Caskを利用してminikubeをインストールします。
$ brew cask install minikube
Hyperkit driverをダウンロードして配置します。
$ curl -LO https://storage.googleapis.com/minikube/releases/latest/docker-machine-driver-hyperkit \ && chmod +x docker-machine-driver-hyperkit \ && sudo mv docker-machine-driver-hyperkit /usr/local/bin/ \ && sudo chown root:wheel /usr/local/bin/docker-machine-driver-hyperkit \ && sudo chmod u+s /usr/local/bin/docker-machine-driver-hyperkit
KubernetesのCLIであるkubectl
をインストールします。
$ brew install kubectl
これでminikubeを起動する準備が整いました。
minikubeの起動
Hyperkit driverを利用するので、--vm-driver=hyperkit
を指定して起動し、Kubernetesのcontextをminikubeに向けます。
minikubeが使えるリソースは--cpu=4
や--memory=4096
と指定できますので、利用するホストマシーンのスペックにあわせて調整してください。
$ minikube start --vm-driver=hyperkit $ kubectl config use-context minikube
なお、筆者の環境では何度かminikubeが起動しないこともありました。
そのような場合、rm -rf ~/.minikube
と一旦環境をリセットしてから起動するとうまくいきました。
Zaleniumの起動
Dockerだけで起動していたZaleniumでは、/var/run/docker.sock
をマウントすることで、ブラウザが動くコンテナをオートスケールさせることができていました。
Kubernetesにおいては、実際にブラウザが動くPodをオートスケールさせるために、ServiceAccountが必要になります。
$ kubectl create serviceaccount zalenium
作成したServiceAccountを利用してZaleniumのDeploymentを作成します。
ZaleiniumはKubernetes利用時には、app=zalenium
というラベルを利用しているので、作成時に指定しています。
$ kubectl run zalenium \ --image=dosel/zalenium:3.8.1c \ --overrides='{"spec": {"template": {"spec": {"serviceAccount": "zalenium"}}}}' \ --labels=app=zalenium,role=grid \ --port=4444 \ -- start --chromeContainers 1 \ --firefoxContainers 0 \ --seleniumImageName elgalu/selenium:3.8.1-p3 \ --videoRecordingEnabled false \ --sendAnonymousUsageInfo false
作成したDeploymentに対応するServiceを作成してアクセスできるようにします。
$ kubectl expose deployment zalenium --type=NodePort service "zalenium" exposed
初回作成時にはDockerイメージを取得する時間のため少々待つ必要があります。
kubectl get pods
によりPodの状況を確認します。
$ kubectl get pods NAME READY STATUS RESTARTS AGE zalenium-40000-547b2 1/1 Running 0 53m zalenium-57d6bb658f-s7vrb 1/1 Running 0 53m
上記、zalenium-40000-547b2
となっているのが、ブラウザが動くSelenium Nodeです。この40000は連番で、オートスケールして台数が増えるたびに数が増えていきます。
今回は起動のオプションでGoogle Chromeのコンテナを1つだけ作ると指定しているので合計で1つ起動しています。
また、zalenium-57d6bb658f-s7vrb
となっているのがZalenium本体です。
両者ともRunningになったら、起動は完了しているので、minikubeのipアドレスおよびZalenium ServiceのnodePortからSelenium GridのURLを調べます。
$ echo http://$(minikube ip):$(kubectl get service zalenium \ -o go-template='{{(index .spec.ports 0).nodePort}}')/wd/hub http://192.168.64.10:31243/wd/hub
Zaleniumの動作確認
ZaleniumのURLが取得できたので動作を確認します。
require "selenium-webdriver" caps = Selenium::WebDriver::Remote::Capabilities.chrome( "name" => "hello zalenium", "recordVideo" => true ) driver = Selenium::WebDriver.for(:remote, url: "http://192.168.64.10:31243/wd/hub", # (1) desired_capabilities: caps ) # あとはブラウザを好きに操作してください driver.get("http://www.selenium.jp/") driver.quit
上記のスクリプトをselenium_script.rb
として保存し、下記のように実行してください。
なお、スクリプト中(1)
の部分は上記のSelenium GridのURLが使われてますので、実行環境に応じて読み替えてください。
$ gem install selenium-webdriver $ ruby selenium_script.rb
スクリプトの実行に伴い、http://192.168.64.10:31243/grid/admin/live
でブラウザ動作のライブプレビューが、http://192.168.64.10:31243/dashboard/
で録画されたダッシュボードが確認できます。
何度かスクリプトを実行すると、ブラウザを動かすコンテナが動的に作成されて動作することが確認できます。
GKEでZaleniumを動かす
このように、ローカルに立てたminikube上でZaleniumの動作が確認できました。 そこで、今度はGKEで試してみましょう。
まずは、Google Cloud PlatformのドキュメントをみてGCPの設定とgcloud
ツールの設定を行ってください。
Kubernetesクラスタの作成
まずはKubernetesを動かすためのクラスタを作成します。
$ gcloud container clusters create zalenium \ --num-nodes 1 \ --machine-type g1-small
こちらはGCPのコンソールから作成することも可能なので、心配な人はGUIで作成してください。 クラスタを作成したらクラスタを操作するための認証情報を取得します。
$ gcloud container clusters get-credentials zalenium
クレデンシャルを取得すると、kubectl config current-context
で取得できるcontextがGKEに自動的に変更されます。
これでZaleniumを起動する準備ができました。
Zaleniumの起動
基本はminikubeと同様に実行できるのですが、クラウド上に作成した場合は第三者にアクセスされる可能性があるので今回はZaleniumに対してBasic認証をかけておきます。
Basic認証は--gridUser
と--gridPassword
で指定できます。
$ kubectl create serviceaccount zalenium $ kubectl run zalenium \ --image=dosel/zalenium:3.8.1c \ --overrides='{"spec": {"template": {"spec": {"serviceAccount": "zalenium"}}}}' \ --labels=app=zalenium,role=grid \ --port=4444 \ -- start --chromeContainers 1 \ --firefoxContainers 0 \ --seleniumImageName elgalu/selenium:3.8.1-p3 \ --videoRecordingEnabled false \ --sendAnonymousUsageInfo false \ --gridUser swet --gridPassword test
この作成したDeploymentは以下のようにGKEのServiceとして公開することができます。
$ kubectl expose deployment zalenium --type=LoadBalancer
LoadBalancer起動後、以下のコマンドでSelenium GridのURLが取得できます。
$ echo http://swet:test@$(kubectl get service zalenium \ -o go-template='{{(index .status.loadBalancer.ingress 0).ip}}:{{(index .spec.ports 0).port}}')/wd/hub http://test:swet@35.190.235.227:4444/wd/hub
ここでは、Basic認証の情報がURLについているので、--gridUser
と--gridPassword
を変えていた場合は適宜読み替えてください。
このBasic認証情報付きのURLはそのまま、先程のスクリプトの(1)
のURLを置き換えて利用することができます。
また、Zaleniumのライブプレビュー画面とダッシュボードもBasic認証で守られていることが確認できます。
ちなみに、下のスクリーンショットはGKEを使って10並列でブラウザを動かしている様子です。
クラスタの削除
以上、GKEでZaleniumを利用可能なことがわかったのでクラスタを削除します。
$ gcloud container clusters delete zalenium
まとめ
以上のようにKubernetesを利用してクラウド上でZaleniumを利用可能となりました。 今回は導入手順を紹介するだけで実践的な内容は最小限にとどめています。 運用上注意することや工夫すること等は今後も紹介していきたいと思いますので楽しみにしていてください。
それでは楽しいクラウドでZaleniumライフを。