メルカリの自動化&品質保証グループ(Automation & QA Group:通称AQA)の 根本 征 です。
私は普段、テスト自動化・CI / CD 改善・その他社内の生産性を上げるための自動化を行っています。
今回は、最近私たちが行なっているメルカリWeb版のUIテスト自動化と、その自動テスト環境についてご紹介したいと思います。
- UI自動テスト環境に関する課題
- Selenium Grid を Azure Kubernetes Service(AKS) 上で構築する
- Zaleniumを試す
- Azure Kubernetes Service(AKS)で受けられる恩恵
- おわりに
メルカリWeb版のUIテスト自動化について
まずは簡単に、メルカリWeb版のUIテスト自動化について紹介します。
以前 @AHA-oretama が発表した資料も参考にしていただければと思います。
これまでメルカリではモバイルアプリ (iOS / Android) をメインに開発が行われ、テスト自動化もそれらをターゲットに行なっていました。
しかし、様々なお客さまに使っていただくために、現在Web版の開発も活発に行われています。
https://www.itmedia.co.jp/news/articles/1903/12/news060.html
技術的な部分だと Mercari Tech Conf 2018 でも発表がありましたが、マイクロサービス化された新しいアーキテクチャへの移行を進めています。
Webの場合、モバイルアプリと比較するとリリースサイクルが短く、さらにマイクロサービス化されていくことでそれぞれのサービス毎にリリースできるようになります。
このような状況の中、品質を保ちながらより早いリリース・フィードバックを実現する ために、去年終わりから今年にかけてUIテスト自動化を進めてきました。
UI自動テスト環境に関する課題
WebのUIテスト自動化はモバイルアプリと比較すると実行時間も早く、安定しやすいです。
今回はテストフレームワークとして WebdriverIO を採用したのですが、ドキュメントも充実しており、ある程度のカバレッジを上げることができました。
しかし、これらのテストを実行する環境の構築に苦労していました。
クラウド上で実行するのを前提に、最初は CircleCI などのマネージドサービスを使うことを検討していました。
最近だとヘッドレスブラウザ (Chrome, Firefox) が利用できることによって、それらのサービスだけで十分にテストを実行できると考えたからです。
しかし、社内の検証環境ではIPアドレスベースでアクセスが制限されている箇所があり、これらのサービスからアクセスができませんでした。
IPアドレスを検証環境のホワイトリストに追加して回避することもできますが、CircleCI などのサービスだと基本的にはIPアドレスが実行毎に変わってしまうため、これらに対応することができませんでした。
そのためこれまでは一時的にローカルのマシンで実行させていましたが、このままだと このUIテストの実行頻度が増えた際にスケールさせることができず、開発スピードに追いつくことができない と感じました。
そこで今回、Azure Kubernetes Service(AKS) 上で Selenium Grid を作成することでこの問題を解決できないか試してみました。
Selenium Grid を Azure Kubernetes Service(AKS) 上で構築する
まずIPアドレスによる制限の問題を解決するために、Azure 上で Kubernetes クラスタを作成する際にアドオンとしてHTTPアプリケーションルーティングの有効化をします。
これによって Static IP が付与され、このクラスタ内部からのアクセスは全てこの Static IP からとなります。
後はこのIPアドレスを検証環境のホワイトリストに追加することによって、IPアドレスによる制限の問題は解決することができました。
次に、このクラスタ内で Selenium Grid 環境を作っていきます。
Selenium Grid の Docker Image(Hub, Node)は公式で提供されています。
また、Kubernetes の GitHub レポジトリでは、Selenium Grid を Kubernetes 上で構築するためのマニフェストファイル・解説があります。
まず、Selenium Grid の Node と Hub の pod を Deployment から生成します。
Node の環境変数で Hub への Host, Port を指定することで、Hub へ接続させることができます。
# Node(Chrome) apiVersion: v1 kind: Deployment metadata: labels: run: selenium-node-chrome name: selenium-node-chrome spec: replicas: 2 selector: matchLabels: run: selenium-node-chrome template: metadata: labels: app: selenium-node-chrome spec: containers: - name: selenium-node-chrome image: selenium/node-chrome:3.141 env: - name: HUB_HOST value: "selenium-hub" - name: HUB_PORT value: "4444"
# Hub apiVersion: v1 kind: Deployment metadata: labels: run: selenium-hub name: selenium-hub spec: replicas: 1 selector: matchLabels: run: selenium-hub template: metadata: labels: run: selenium-hub spec: containers: - image: selenium/hub:3.141 name: selenium-hub ports: - containerPort: 4444 protocol: TCP livenessProbe: httpGet: path: /wd/hub/status port: 4444 initialDelaySeconds: 30 timeoutSeconds: 5 readinessProbe: httpGet: path: /wd/hub/status port: 4444 initialDelaySeconds: 30 timeoutSeconds: 5
そして Hub は Service として公開します。
apiVersion: v1 kind: Service metadata: labels: app: selenium-hub-service name: selenium-hub-service spec: ports: - port: 80 name: selenium-grid targetPort: 4444 selector: run: selenium-hub sessionAffinity: None type: LoadBalancer
成功すると Selenium Grid のコンソール画面に Node が表示されます。
Selenium Grid の Node の数は下記のコマンドで増減させることが可能です。
$ kubectl scale deployment selenium-node-chrome --replicas=10
では実際にこの Selenium Grid に対して並列でテストを流します。
WebdriverIO では設定ファイル wdio.conf.js
の maxInstances
を変更することでその並列数を簡単に変更することができます。
exports.config = { hostname = 'hoge.aksapp.io' port = 80 path = '/wd/hub' maxInstances: 5 }
試しに Chrome の Node を5台用意し5並列実行させたところ、1並列の実行時間よりも約1/4になりました。
Zaleniumを試す
Selenium Grid をベースに作られた OSS ツールとして Zalenium があります。
Zalenium に関する日本語の記事では下記などがあります。
Zalenium では Selenium Grid に追加して以下のメリットがあります
- テストのライブプレビュー機能
- テストの録画機能
- Selenium Grid の Node の オートスケール機能
Kubernetes との相性もよく、公式ページにあるチュートリアルを参考に Azure Kubernetes Service でもデプロイさせることができます。
実際にこの環境に向けてテストを実行させると、ライブプレビュー画面を確認することができます。
先ほどの Selenium Grid と比較すると構築も簡単でしたが、個人的には Kubernetes の仕組みも理解する上で、一回 Selenium Grid の環境を構築しておいてよかったと感じました。
今後 Zalenium を運用していく中で気づいたことなどあれば紹介していきたいと思います。
Azure Kubernetes Service(AKS)で受けられる恩恵
ここまでの環境だと、どの Kubernetes マネージドサービスであっても同様のを作ることができると思います。
今回は Azure Kubernetes Service(AKS) を試しましたが、個人的には下記の二点が特徴的と考えています。
将来的に仮想ノード(Virtual Kubelet)が利用できる
先ほどは5並列でUIテストを実行させていましたが、複数のブラウザサポートやより短い実行時間を目指すとなると、より多くの並列実行数が必要になっていきます。
並列実行数を増やすために Pod の数も増やす必要がありますが、リソースを増やすために Kubernetes Node の数も増やす必要があります。
通常だと Kubernetes Node の立ち上げには一定の時間がかかってしまい、必要な時に瞬時にリソースを増減させたい今回のニーズにはあまり適していません。
AKS では現在プレビュー版で仮想ノード(Virtual Kubelet) が提供されており、こちらを使うことによって Kubernetes Nodeを瞬時に増減させることができます。
Kubernetes のマニフェストファイルで、nodeSelector を下記のように Virtual Kubelet に変えることで利用することができます。
nodeSelector: kubernetes.io/role: agent beta.kubernetes.io/os: linux type: virtual-kubelet tolerations: - key: virtual-kubelet.io/provider operator: Exists - key: azure.com/aci effect: NoSchedule
使ったリソースのみ課金されるため、今回のような並列で自動テストを実行させるケースとはとても相性が良いと感じました。
一部の地域ではプレビュー版が出ていますが、東日本リージョンでは現時点では利用できないため、今後利用可能になることを期待しています。
Windows コンテナインスタンスを利用することができる
先ほどの Virtual Kubelet では Linux の他に Windows コンテナインスタンスを利用することができます。
ブラウザの自動テストの場合、今後 Edge ブラウザーなど Windows 環境でテストしたいという状況が出てくるかもしれません。
そのような場合に必要なタイミング・リソースのみで使うことができるのはとても便利と感じましたし、AKS ならではと感じました。
こちらも現時点では東日本リージョンで利用できないのですが、興味があるため利用できるようになったら実際に試してみたいと思います。
おわりに
今回は、Selenium Grid・Zalenium を AKS で構築することで、WebのUI自動テストを格段にスケールできるようになりました。
試しに Kubernetes Node・Pod を増やして並列実行させたところ、1時間 → 6~7分 で実行させることができ、未来を感じました。
このレベルになると、より開発サイクルの中にUIテストを入れる事が可能になりそうです。
しかし、これ以外にも 品質を保ちながらより早いリリース・フィードバックを実現する 世界を目指すにはやらないといけない事があります。
- 並列実行の増加に合わせて検証環境もスケールするよう改善する
- 並列実行時にテストの分散が最適化されるようにする
- 開発のデプロイメントパイプラインに組み込む
- テスト自体の安定化
これらの課題を解決しつつ、今後は仮想ノード(Virtual Kubelet)なども試してこの自動テスト環境を改善していきたいと思います。
また、これらの環境はまだ運用し始めたばかりなので、今度運用していく中で気づいたことなどあれば紹介していきたいと思います。
最後にですが、今回の環境構築に当たって日本マイクロソフトの寺田さん(@yoshitera) にサポートしていただきました、本当にありがとうございました。