【IaCで作るselenium環境】06_Androidコンテナを構築する(テスト実行編)

直近の関連エントリ

――――――――――――――――――――――――――――――――――

こんにちは。SHIFTのスクラムマスター・テスト自動化エンジニアの石丸です。

前回、Ansibleを使ってAzureVM上にAndroidコンテナを準備しました。

お待たせしました。
今回とうとうAndroidコンテナを動かすテストを実行してゆきます。



■今回のテーマ

今回のテーマは「Androidコンテナでのテスト実行」です。
いやー、ここに辿り着くまで結構長かった。。


■前提

・DockerDesktop Version 3.0.0(現時点での最新)
・windows環境での構築
・第5回までの内容が作業済みであること


■前回のおさらい

前回の最後はこんな感じでした。

今回の構成_05

AnsibleでVMにSelenoidが構築されています。
またAndroidコンテナも準備が整っています。


■テストコードの準備

実は第2回でAndroidのテストケースはaerokubeのGitHubから取得しているものの、一旦削除しています。
こちらを復活させます。DemoTestと同じフォルダに以下のソースコードを置きます。

AndroidDemoTest.java
テストコードの内容:電卓アプリを起動して、2+7を行う

package com.aerokube.selenoid;

import io.appium.java_client.MobileBy;
import io.appium.java_client.MobileElement;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.openqa.selenium.remote.RemoteWebDriver;

import java.net.URL;

import static com.aerokube.selenoid.DemoTest.takeScreenshot;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.junit.Assert.assertThat;

public class AndroidDemoTest {

   private static final By BUTTON_2 = MobileBy.xpath("//android.widget.Button[contains(@resource-id,'digit_2') and @text='2']");
   private static final By BUTTON_PLUS = MobileBy.xpath("//android.widget.Button[@resource-id='com.android.calculator2:id/op_add']");
   private static final By BUTTON_7 = MobileBy.xpath("//android.widget.Button[contains(@resource-id,'digit_7') and @text='7']");
   private static final By BUTTON_EQUALS = MobileBy.xpath("//android.widget.Button[@resource-id='com.android.calculator2:id/eq']");
   private static final By RESULT_FIELD = MobileBy.xpath("//android.widget.EditText[@resource-id='com.android.calculator2:id/formula']");
   
   private RemoteWebDriver driver;
   
   @Before
   public void openDriver() throws Exception {
       final DesiredCapabilities device = new DesiredCapabilities();
       device.setCapability("deviceName", "android");
       device.setCapability("version", "8.1");
       device.setCapability("appPackage", "com.android.calculator2");
       device.setCapability("appActivity", "com.android.calculator2.Calculator");
       device.setCapability("adbExecTimeout", "360000");
       device.setCapability("androidInstallTimeout", "360000");
       device.setCapability("skin", "WXGA720");
       device.setCapability("enableVNC", true);
       device.setCapability("enableVideo", true);
       device.setCapability("enableLog", true);
       
       driver = new RemoteWebDriver(new URL(
               "http://test:test-password@172.17.0.1:8083/wd/hub"
       ), device);
   }
   
   @Test
   public void browserTest() throws Exception {
       try {
           driver.findElement(BUTTON_2).click();
           driver.findElement(BUTTON_PLUS).click();
           driver.findElement(BUTTON_7).click();
           driver.findElement(BUTTON_EQUALS).click();
       } finally {
           takeScreenshot(driver);
       }
   }
   
   @After
   public void closeDriver(){
       if (driver != null){
           driver.quit();
           driver = null;
       }
   }
}

これとは別に第2回で準備したDemoTestの書き換えを行ってMobileChrome環境が起動するようにします。
書き換えるのは以下の部分です。

DemoTest.java

browser.setCapability("version", "mobile-75.0");
driver = new RemoteWebDriver(new URL(
       "http://test:test-password@172.17.0.1:8083/wd/hub"
), browser);

バージョンとリモート先のURLだけ修正すればOKです!

またdemo-testフォルダ直下にあるpox.xmlのdependenciesに以下を追加します。

pom.xml

<!-- https://mvnrepository.com/artifact/io.appium/java-client -->
<dependency>
   <groupId>io.appium</groupId>
   <artifactId>java-client</artifactId>
   <version>7.3.0</version>
</dependency>


■テスト実行!その前に

さて、あとはテスト実行するのみ!と行きたいですがまだ実行できません。
Ggrからルーティング設定と、VMのポート設定が出来ていませんね。

今回の構成_06_前提

これをやります。

ポートの設定
Selenoidポートが未登録なのでこちらを開けます。
VMを選択し、メニューからネットワークを選びます。

ネットワーク

受信ポートの規制一覧が表示されますので、画面左側にある「受信ポートの規制を追加する」を押します。

追加ボタン

VM内に潜って確認。
Selenoidにforwordしているポートは8083です。

PS C:\WINDOWS\system32> ssh -i ~/.ssh/selenoidvm_key.pem azureuser@myselenoidvm.eastus.cloudapp.azure.com
Welcome to Ubuntu 18.04.5 LTS (GNU/Linux 5.4.0-1031-azure x86_64)

(中略)

azureuser@selenoidvmw:~$ sudo docker container ls -a
CONTAINER ID   IMAGE                                    COMMAND                  CREATED       STATUS                        PORTS                    NAMES
03e7707ed568   selenoid/video-recorder:latest-release   "/entrypoint.sh"         2 hours ago   Up About a minute (healthy)                            video-recorder
96bb3e328838   aerokube/selenoid:1.10.0                 "/usr/bin/selenoid -…"   2 hours ago   Up About a minute (healthy)   0.0.0.0:8083->4444/tcp   selenoid

ですので8083ポートを許可します。

追加

追加されました。

ポート許可

Ggrの設定
第2回で準備したGgrのtest.xmlに、AndroidとMobileChrome、AzureのDNS名を設定します。

test.xml

<qa:browsers xmlns:qa="urn:config.gridrouter.qatools.ru">
<browser name="firefox" defaultVersion="77.0">
   <version number="77.0">
       <region name="1">
       <host name="172.17.0.1" port="4444" count="2" vnc="ws://172.17.0.1:4444/vnc" />
       <host name="192.168.111.111" port="8447" count="2" vnc="ws://192.168.111.111:8447/vnc" />
       </region>
   </version>
</browser>
<browser name="chrome" defaultVersion="84.0">
   <version number="83.0">
       <region name="1">
       <host name="172.17.0.1" port="4444" count="1" vnc="ws://172.17.0.1:4444/vnc" />
       <host name="192.168.111.111" port="8447" count="2" vnc="ws://192.168.111.111:8447/vnc" />
       </region>
   </version>
   <version number="84.0">
       <region name="1">
       <host name="172.17.0.1" port="4444" count="1" vnc="ws://172.17.0.1:4444/vnc" />
       <host name="192.168.111.111" port="8447" count="2" vnc="ws://192.168.111.111:8447/vnc" />
       </region>
   </version>
   <version number="mobile-75.0">
       <region name="1">
       <host name="myselenoidvm.eastus.cloudapp.azure.com" port="8083" count="1" vnc="ws://myselenoidvm.eastus.cloudapp.azure.com:8083/vnc" />
       </region>
   </version>
</browser>
<browser name="android" defaultVersion="8.1">
   <version number="8.1">
       <region name="1">
       <host name="myselenoidvm.eastus.cloudapp.azure.com" port="8083" count="1" vnc="ws://myselenoidvm.eastus.cloudapp.azure.com:8083/vnc" />
       </region>
   </version>
</browser>
</qa:browsers>

test.xmlを修正したら、ローカルPCのGgrを再構築します。

PS C:\tmp\docker\ggr\ggr> docker-compose ps
  Name                  Command                  State                Ports
-------------------------------------------------------------------------------------
ggr           /usr/bin/ggr -listen :4444 ...   Up (healthy)   0.0.0.0:8083->4444/tcp
ggr-ui        /usr/bin/ggr-ui -quota-dir ...   Up (healthy)   0.0.0.0:8888->8888/tcp
selenoid-ui   /selenoid-ui --selenoid-ur ...   Up (healthy)   0.0.0.0:18080->8080/tcp

PS C:\tmp\docker\ggr\ggr> docker-compose down -v
Stopping selenoid-ui ... done                                                                                                                                                Stopping ggr-ui      ... done                                                                                                                                                Stopping ggr         ... done                                                                                                                                                Removing selenoid-ui ... done                                                                                                                                                Removing ggr-ui      ... done                                                                                                                                                Removing ggr         ... done                                                                                                                                                Removing network ggr_default
Removing volume ggr_ggr
Removing volume ggr_ggr-ui

PS C:\tmp\docker\ggr\ggr> docker-compose up -d --build --force-recreate
Creating network "ggr_default" with the default driver
Creating volume "ggr_ggr" with default driver
Creating volume "ggr_ggr-ui" with default driver
Building ggr
Step 1/7 : FROM aerokube/ggr:latest-release
---> aca0cf2239c9
Step 2/7 : MAINTAINER presales
---> Using cache
---> 23ee4cf49ce3
Step 3/7 : RUN set -x
---> Using cache
---> 1851e81d1464
Step 4/7 : RUN apk --update --no-cache --virtual build-dependencies add apache2-utils
---> Using cache
---> d383e8976df9
Step 5/7 : RUN mkdir -p /etc/grid-router/quota/
---> Using cache
---> 671ceab19d6b
Step 6/7 : COPY test.xml /etc/grid-router/quota/test.xml
---> 44b5c7f144e2
Step 7/7 : RUN htpasswd -bc /etc/grid-router/users.htpasswd test test-password
---> Running in b7ff54098813
Adding password for user test
Removing intermediate container b7ff54098813
---> afb217baaa4d
Successfully built afb217baaa4d
Successfully tagged aerokube/ggr:latest
Building ggr-ui
Step 1/5 : FROM aerokube/ggr-ui:latest-release
---> 0a5f4d02db09
Step 2/5 : MAINTAINER presales
---> Using cache
---> 6efc6694ed9e
Step 3/5 : RUN set -x
---> Using cache
---> 50cbda216a71
Step 4/5 : RUN mkdir -p /etc/grid-router/quota/
---> Using cache
---> af023ff1c900
Step 5/5 : COPY test.xml /etc/grid-router/quota/test.xml
---> eb89231371bb

Successfully built eb89231371bb
Successfully tagged aerokube/ggr-ui:latest
Creating ggr         ... done
Creating ggr-ui      ... done
Creating selenoid-ui ... done

Ggrの設定が有効になっているか確認します。
http://localhost:8083/quota
basic認証を聞かれるので入力します。

ggrアクセス
画像8

読み込まれていますね。

Ggr-UI(Selenoid-UI)も確認します。
http://localhost:18080/#/

画像10

quotaの数も増え、selenoid-UIもListen出来ているようです。


■今度こそテスト実行!

テストを起動します。

第2回で準備したmavenコンテナを再実行します。
修正したテストコードを格納しているフォルダ「demo-test」直下で以下のコマンドを打ちます。

PS C:\tmp\docker\mvn> docker run -it --net="bridge" --name demo-test -v ${PWD}/demo-tests:/usr/src/mymaven -w /usr/src/mymaven maven mvn clean install test

[INFO] Scanning for projects...
[WARNING]
[WARNING] Some problems were encountered while building the effective model for com.aerokube.selenoid:demo-test:jar:1.0-SNAPSHOT
[WARNING] 'build.plugins.plugin.version' for org.apache.maven.plugins:maven-source-plugin is missing. @ line 42, column 21
[WARNING]
[WARNING] It is highly recommended to fix these problems because they threaten the stability of your build.
[WARNING]
[WARNING] For this reason, future Maven versions might no longer support building such malformed projects.
[WARNING]
[INFO]
[INFO] ------------------< com.aerokube.selenoid:demo-test >-------------------
[INFO] Building demo-test 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------

(中略)

[INFO] Installing /usr/src/mymaven/target/demo-test-1.0-SNAPSHOT.jar to /root/.m2/repository/com/aerokube/selenoid/demo-test/1.0-SNAPSHOT/demo-test-1.0-SNAPSHOT.jar
[INFO] Installing /usr/src/mymaven/pom.xml to /root/.m2/repository/com/aerokube/selenoid/demo-test/1.0-SNAPSHOT/demo-test-1.0-SNAPSHOT.pom
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ demo-test ---
[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] skip non existing resourceDirectory /usr/src/mymaven/src/main/resources
[INFO]
[INFO] --- maven-compiler-plugin:2.3.2:compile (default-compile) @ demo-test ---
[INFO] No sources to compile
[INFO]
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ demo-test ---
[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] Copying 1 resource
[INFO]
[INFO] --- maven-compiler-plugin:2.3.2:testCompile (default-testCompile) @ demo-test ---
[INFO] Nothing to compile - all classes are up to date
[INFO]
[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ demo-test ---
[INFO] Skipping execution of surefire because it has already been run for this configuration
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  06:15 min
[INFO] Finished at: 2020-12-15T16:34:05Z
[INFO] ------------------------------------------------------------------------

こんな感じでテストが正常終了します。

ちなみに実行中はコンテナ内でエミュレータ、ADB、Appiumの処理を行っているため、起動にちょっと時間がかかかります。

なお実行中にVMに潜ってdocker container ls -aするとAndroidコンテナの起動しているのがわかりますので、logsコマンドで中身を出力すると実行の様子も確認できます。

azureuser@selenoidvm:~$ sudo docker container ls -a

CONTAINER ID   IMAGE                                    COMMAND                  CREATED          STATUS                    PORTS                                              NAMES
5765825e9172   selenoid/video-recorder:latest-release   "/entrypoint.sh"         56 seconds ago   Up 55 seconds                                                                wizardly_burnell
c2dd67145a4c   selenoid/android:8.1                     "/entrypoint.sh"         57 seconds ago   Up 55 seconds             4444/tcp, 5900/tcp, 7070/tcp, 8080/tcp, 9090/tcp   loving_mccarthy
03e7707ed568   selenoid/video-recorder:latest-release   "/entrypoint.sh"         3 hours ago      Up 17 minutes (healthy)                                                      video-recorder
96bb3e328838   aerokube/selenoid:1.10.0                 "/usr/bin/selenoid -…"   3 hours ago      Up 43 minutes (healthy)   0.0.0.0:8083->4444/tcp                             selenoid

azureuser@selenoidvm:~$ sudo docker container logs -f loving_mccarthy
Waiting X server...
Waiting X server...
Waiting X server...
Waiting X server...
Logging to: /tmp/fluxbox.log
Waiting X server...
Waiting X server...
Waiting X server...
* daemon not running; starting now at tcp:5037

(以下略)


暫くしてselenoiu-UIで起動が確認できます。

android8.1起動

android起動

mobile chrome起動

mobilechrome起動


■動作確認

Ggrから複数のSelenoidへ接続するため、第1回のときのようにvideoフォルダが(特定)表示できません。
今回はscpコマンドでVMにアクセスし、videoをダウンロードしてきます。

PS C:\tmp\docker\mvn> scp -i ~/.ssh/selenoidvm_key.pem azureuser@myselenoidvm.eastus.cloudapp.azure.com:/usr/local/selenoid/video/* c:\tmp\docker\mvn\

androidの動作
再生してみます。

2+7の計算が確認できます。

mobileChromeの動作
同じく再生してみます。

第1回と同じ動作がAndroid上のChromeで実行されることが確認できます。

今回作成された構成

今回の構成_06


■SelenoidのAndroidコンテナに対する率直な感想

ここまで組んでおいてアレですが、実際に動かした感想として遅かったり不安定だったりと、現時点では実用に耐えうるものではないかなーという印象です。

ただAerokubeのissueを見ると結構海外では実績があるようで。。

VMに割り当てたリソースがしょぼいからか、私の構築がイケてないからか。。引き続き検証していこうと思います。


■まとめ

実際の構築手順

1. AndroidとMobileChromeテストコードの準備をする
2. pom.xmlを修正する
3. AzureVMのSelenoidポートを開ける
4. Ggrのtest.xmlを修正して起動ルートを作る
5. Ggrコンテナを再構築する
6. テストを起動する(第2回で準備したコンテナの実行)

==================================================
不安定ではありましたが、Selenoidを使用してAndroidコンテナにてテストを実行することができました。

さて、ここまでの手順でいささか面倒だったのは第4回のVM準備です。
GUIでポチポチ操作はやっぱり手間ですよね。

ということで次回はこれをTerraformを使用してコマンド一発(正確には3発ぐらい)で構築できるようします。

ではでは。

――――――――――――――――――――――――――――――――――

執筆者プロフィール:石丸圭
スクラムを中心にテストのアジリティーを高めるべく
日々仕事のリードタイム・プロセスタイムの圧縮に奮闘中。
3児のパパ(7歳4歳1歳)。

MUPうさぎクラス。
個人的なご相談はインスタDMにてどうぞー。
Instagram:@theboyalex

【ご案内】
テスト自動化のご相談は以下までお気軽にご連絡ください。
https://forms.office.com/Pages/ResponsePage.aspx?id=IkyjGtUOzUeqMMEbzjGdlSf__O4V1URMn-5BpGP8xd9UNE9ESkRPUEs1Wk9FM0REU1BXODFBSkI0MC4u

お問合せはお気軽に
https://service.shiftinc.jp/contact/

SHIFTについて(コーポレートサイト)
https://www.shiftinc.jp/

SHIFTのサービスについて(サービスサイト)
https://service.shiftinc.jp/

SHIFTの導入事例
https://service.shiftinc.jp/case/

お役立ち資料はこちら
https://service.shiftinc.jp/resources/

SHIFTの採用情報はこちら
https://recruit.shiftinc.jp/career/


みんなにも読んでほしいですか?

オススメした記事はフォロワーのタイムラインに表示されます!