Mercari Engineering Blog

We're the software engineers behind Mercari. Check out our blog to see the tech that powers our marketplace.

メルカリWeb版のUIテスト自動化で目指している世界と、そのために作った Selenium Grid・Zalenium 環境 on Azure Kubernetes Service(AKS)

メルカリの自動化&品質保証グループ(Automation & QA Group:通称AQA)の tadashi0713 です。

私は普段、テスト自動化・CI / CD 改善・その他社内の生産性を上げるための自動化を行っています。

今回は、最近私たちが行なっているメルカリWeb版のUIテスト自動化と、その自動テスト環境についてご紹介したいと思います。

メルカリWeb版のUIテスト自動化について

まずは簡単に、メルカリWeb版のUIテスト自動化について紹介します。

以前 @AHA-oretama が発表した資料も参考にしていただければと思います。



これまでメルカリではモバイルアプリ (iOS / Android) をメインに開発が行われ、テスト自動化もそれらをターゲットに行なっていました。

しかし、様々なお客さまに使っていただくために、現在Web版の開発も活発に行われています。

メルカリ、PC向けサービス強化へ 機能制限撤廃、スマホと同等に - ITmedia NEWS

技術的な部分だと Mercari Tech Conf 2018 でも発表がありましたが、マイクロサービス化された新しいアーキテクチャへの移行を進めています。

dev.classmethod.jp

Webの場合、モバイルアプリと比較するとリリースサイクルが短く、さらにマイクロサービス化されていくことでそれぞれのサービス毎にリリースできるようになります。

このような状況の中、品質を保ちながらより早いリリース・フィードバックを実現する ために、去年終わりから今年にかけてUIテスト自動化を進めてきました。

f:id:tadashi-nemoto0713:20190411161526p:plain:w800
アプリと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アプリケーションルーティングの有効化をします。

f:id:tadashi-nemoto0713:20190410171351p:plain:w700
HTTPアプリケーションルーティングの有効化

docs.microsoft.com

これによって Static IP が付与され、このクラスタ内部からのアクセスは全てこの Static IP からとなります。

後はこのIPアドレスを検証環境のホワイトリストに追加することによって、IPアドレスによる制限の問題は解決することができました。

次に、このクラスタ内で Selenium Grid 環境を作っていきます。

Selenium Grid の Docker Image(Hub, Node)は公式で提供されています。

github.com

また、Kubernetes の GitHub レポジトリでは、Selenium Grid を Kubernetes 上で構築するためのマニフェストファイル・解説があります。

github.com

まず、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 が表示されます。

f:id:tadashi-nemoto0713:20190409214102j:plain
Selenium Grid

Selenium Grid の Node の数は下記のコマンドで増減させることが可能です。

$ kubectl scale deployment selenium-node-chrome --replicas=10

では実際にこの Selenium Grid に対して並列でテストを流します。

WebdriverIO では設定ファイル wdio.conf.jsmaxInstances を変更することでその並列数を簡単に変更することができます。

exports.config = {
  hostname = 'hoge.aksapp.io'
  port = 80
  path = '/wd/hub'
  maxInstances: 5
}

webdriver.io

試しに Chrome の Node を5台用意し5並列実行させたところ、1並列の実行時間よりも約1/4になりました。

Zaleniumを試す

Selenium Grid をベースに作られた OSS ツールとして Zalenium があります。

opensource.zalando.com

Zalenium に関する日本語の記事では下記などがあります。

swet.dena.com

Zalenium では Selenium Grid に追加して以下のメリットがあります

  • テストのライブプレビュー機能
  • テストの録画機能
  • Selenium Grid の Node の オートスケール機能

Kubernetes との相性もよく、公式ページにあるチュートリアルを参考に Azure Kubernetes Service でもデプロイさせることができます。

実際にこの環境に向けてテストを実行させると、ライブプレビュー画面を確認することができます。

f:id:tadashi-nemoto0713:20190416005220p:plain
Zaleniumで表示されるライブプレビュー画面

先ほどの 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を瞬時に増減させることができます。

docs.microsoft.com

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) にサポートしていただきました、本当にありがとうございました。