こんにちはsekitakaです。
UnitTestだけでなくContextやActivityを使用するconnectedAndroidTestも自動化したいですよね。
しかしconnectedAndroidTestは実機 or エミュレータが必要なので少し自動化しづらく感じると思います。
この記事ではDockerでAndroidエミュレータを起動し、デプロイコンテナからconnectedAndroidTestを実行する方法について紹介します。
使用したサンプルプロジェクトも公開していますので自由に使用してください。
実施した環境
Dockerホスト: macOS Sierra
Dockerの構成
今回はアプリのデプロイ用のdeployコンテナと、Androidエミュレータが実行されるemulatorコンテナの2つを連携して、connectedAndroidTestを実施します。
よってdocker-composeで2つのコンテナの連携を行います。
dockerディレクトリ
docker関連のファイルをプロジェクト直下のdockerディレクトリにまとめています。
docker
├── deploy
│ ├── Dockerfile
│ └── share_by_container
└── docker-compose.yml
deploy
deploy
ディレクトリにはデプロイ用のコンテナのDockerfileとdeployコンテナで永続化されるディレクトリ(share_by_container
)があります。
Dockerfileの内容は以下の通り。
JDK8とAndroidSDKをインストールしています。
FROM ubuntu:16.04
# JDKインストール
RUN apt-get -y update
RUN apt-get -y install openjdk-8-jdk
# Android SDKインストール
RUN apt-get install -y wget unzip
RUN wget https://dl.google.com/android/repository/tools_r25.2.3-linux.zip
RUN mkdir -p /Android/sdk
RUN unzip tools_r25.2.3-linux.zip -d /Android/sdk
# 環境変数
ENV JAVA_HOME /usr/lib/jvm/java-8-openjdk-amd64
ENV ANDROID_HOME /Android/sdk
ENV PATH $ANDROID_HOME/bin:$PATH
emulator
エミュレータはDocker Hubで公開されているイメージをそのまま使用するので、専用のディレクトリは作成していません。
docker-compose.yml
docker-compose.ymlは次のように作成しています。
docker-compose run deploy bash deploy.sh
version: '2'
services:
# アプリのテスト/ビルド用コンテナ
deploy:
build: deploy
volumes:
- ./deploy/share_by_container/android-sdk:/Android/sdk
- ./deploy/share_by_container/dot_gradle:/root/.gradle
- ../:/app
working_dir: /app
# tty: true # コンテナにログインして調査したい場合はコメントイン
depends_on:
- emulator
# エミュレータ実行コンテナ
emulator:
image: mattsawyer/android-emulator
deployコンテナはemulatorに依存する設定にしています。
エミュレータのイメージはmattsawyer/android-emulatorを使用しています。
このエミュレータのイメージは展開すると8GBくらいになるので、ディスクを節約したい場合Dockerfileを調整して、必要なエミュレータのみ含むようにするとよいでしょう。
deploy.sh
deployコンテナでdeploy.sh
を実行することでconnectedAndroidTestの実施をします。
#!/bin/bash
# Android Studioが生成する不要なファイルを削除
rm -f local.properties
# ローカル環境で同意したライセンス情報を書き込み
mkdir -p $ANDROID_HOME/licenses
echo "8933bad161af4178b1185d1a37fbf41ea5269c55" > $ANDROID_HOME/licenses/android-sdk-license
# Android系のコマンドへアクセスできるようにパスを追加
export PATH=$PATH:/Android/sdk/platform-tools:/Android/sdk/tools/bin
# emulatorにadb接続し、deviceの準備が出来るまで待機
ADB_DEVICES=""
adb connect emulator:5555
until grep -q "emulator:5555 device"<<<$ADB_DEVICES;
do
echo "waiting emulator"
adb connect emulator:5555
ADB_DEVICES=`adb devices`
sleep 5
done
adb devices
sleep 60 # apkのインストール可能になるまで待機
# connectedAndroidTest実施
./gradlew clean && \
./gradlew connectedAndroidTest
emulatorが準備できるまで待機しなければならないので、このようになっています。
あくまでも検証した環境ではsleep 60
で十分でしたが、他の環境では調整が必要かもしれません。
またemulatorコンテナを再利用すれば、このように待つ必要はなさそうです。
connectedAndroidTestの実施
いよいよ実施です。
以下のコマンドを実行するとemulatorコンテナとdeployコンテナが起動し、deployコンテナのdeploy.shが実行されます。deploy.shでconnectedAndroidTestを実行しているので、テストの実行ができます。
docker-compose run deploy bash deploy.sh || docker-compose kill
kill
しているのはemulatorコンテナが起動したままになってしまうからです。
以下のようなテスト成功の出力が得られれば成功です。
今回はAndroid Studioで新規作成したばかりのプロジェクトだったので、1testsのみ実行されました。
Starting 1 tests on Android SDK built for x86 - 4.4.2
:app:connectedAndroidTest
BUILD SUCCESSFUL
まとめ
いかがでしたでしょうか。 Docker上で動作するようにしておけば、他の環境でも簡単にCIできる環境ができあがるので、オススメの方法です。またjenkinsのホストも汚れなくて済みます。
少しデプロイに時間がかかるのがデメリットですが、是非CIに取り入れていきたいですね。
サンプルプロジェクトも公開しているので自由に使用してください。