DeNA Testing Blog

Make Testing Fun, Smart, and Delighting End-Users

Android Test Night #1 開催

はじめまして、SWETの金子(theoden9014)です。

今回のエントリーは2017-09-21に第一回目としてSWET主催で開催したAndroid Test Night #1と、そこで「Android SDK with Docker」という題で私が発表した内容についてご紹介したいと思います。

Test Night とは?

Test Nightとは、SWETが主催する主にテストに関係することについて語り合うことを目的とした勉強会です。

昨年11月からiOS Test Nightと呼ばれるiOSに特化したTest Nightを2ヶ月ごとに開催しています。 これまで合計39件の発表がおこなわれ、多数の方に参加していただき、活発な議論がおこなわれる勉強会になっています。

Android Test Night とは?

iOS Test Nightと同様にTest Nightで管理しているイベントです。 今回はAndroidについても同様にテストを対象としたイベントの需要があることがわかり、開催する運びとなりました。

Android Test Night #1

今回はその第1回目です。
15分枠のセッションでは

  • 「コードレビューをより良くする Danger x Android」
  • 「Androidのテストを効率的にするために考えたこと」
  • 「Android E2E Testing at Mercari」

といった、開発プロセス改善についてのセッションや、実際にテストに取り組んでいる事例紹介のセッション。
5分枠のセッションでは

  • 「AndroidSDK with Docker」
  • 「JUnit5とAndroidのテスト」
  • 「Kotlinで書かれたAndroidアプリをBazelでビルドする」
  • 「Android CIをBitriseに移行して開発者・QAが幸せになったこと」
  • 「Clean Architecture & TDD」

といった、CI、テストツールやテスト手法についてのセッション。 といった、様々な内容のセッションがありました。

当日の資料に関してはこちらにアップロードされているので詳細が気になる方はご覧ください。

f:id:swet-blog:20170926194045j:plain Android Test Night #1 登壇時の様子

Application Build with Docker

ここからは私が発表した「Android SDK with Docker」に話を移したいと思います。

あるアプリケーションをCIに載せようとした際、CIでアプリケーションのビルドを可能にする必要があります。

CI毎にビルドに関する設定方法や環境構築はまちまちで、複数のCIを利用する際はそれぞれのCIに対してビルド環境やビルドフローをメンテナンスする必要が出てきます。
近年のサーバーサイドアプリケーションはビルド環境や動作環境をDockerで統一化を図ることが主流となってきていますが、クライアントサイドアプリケーションではそういったアプローチに関する情報が少ない状態だと思います。

そこで今回はクライアントサイドでもDockerによるビルド環境の統一化ができないか検証してみました。

Android SDK with Docker

今回はAndroidアプリケーションに必要なビルド環境をコンテナイメージ化したAndroid SDK imageと、 そのAndroid SDK imageを元にアプリケーションコードを含めてビルドするApplication imageに分けたいと思います。 Android SDK imageを元にアプリケーションコードをmountしてビルドする手段もあります。 しかし、今回はgradleのキャッシュをイメージに含めたいので、Application imageを作る方向にしました。

Dockerのイメージレイヤーは以下の通りです。

alpine image
|
|-- Android SDK image
    |
    |-- Application image

Android SDK image

まずはAndroid SDKを利用できるDockerイメージが必要です。

ここで注意が必要なのはGoogleのAndroid SDK利用規約 (3.4)により、バックアップ目的以外でのコピー及び再配布が禁止とされている点です。 (gfxさんのこちらのブログ記事に詳細が言及されています)

つまり、Androidをビルドする為のDocker imageは自身でビルドする必要があるということです。
しかしながら、Dockerfile自体にAndroidSDKのライセンスは含まれません。 よって、Github上に公開されているものを利用するか自身で記述することでDockerfileを用意し、自身でDocker imageのビルドを行なってください。

Application image

こちらはAndroidアプリケーションと同じディレクトリ内にDockerfileを作成します。 ADD . /projectでアプリケーションコードをイメージに追加する前にgradleのキャッシュを生成しています。 これはDocker imageをビルドする際、命令によって変更が加わるまではDocker imageキャッシュが利用されるという仕様を利用し、最大限にDockerイメージのキャッシュを生かしています。
仮にADD . /projectの後にgradleのキャッシュを生成する処理をしてしまうと、 ADDで追加するアプリケーションコードに変更が加わると、それ以降の処理はDockerイメージのキャッシュが利用されなくなります。

FROM ${ANDROID_SDK_IMAGE}

RUN mkdir -p /tmp/gradle/app
COPY gradlew /tmp/gradle/gradlew
COPY gradle /tmp/gradle/gradle
COPY build.gradle /tmp/gradle/build.gradle
COPY gradle.properties /tmp/gradle/gradle.properties
COPY settings.gradle /tmp/gradle/settings.gradle
COPY app/build.gradle /tmp/gradle/app/build.gradle
COPY app/mastiff.gradle /tmp/gradle/app/mastiff.gradle

WORKDIR /tmp/gradle
RUN ./gradlew

ADD . /project
WORKDIR /project

RUN echo "sdk.dir=$ANDROID_HOME" > local.properties

CMD ["./gradlew", "tasks"]

この状態で、

docker build -t application:$(git rev-parse HEAD) .
docker run --rm -it \
           -v $(pwd)/app/build:/project/app/build \
           application:$(git rev-parse HEAD) \
           ./gradlew build

と実行することで、アプリケーションをビルドすることが可能です。

登壇したセッションの資料にはAndroidエミュレータをDockerで起動しテストを行う方法も記載しております。しかし、エミュレータでのテストはパフォーマンスがよくないので、デバイスファーム等を利用すると良いと思います。

最後に

今回はクライアントサイドアプリケーションのDockerizeに関してご紹介しました。機会があればサーバーサイドアプリケーションのDockerizeについてもご紹介できればと思っております。

Android Test Night #2 の開催時期は未定ですが、2, 3ヶ月に1回程度開催を予定しておりますので、ご興味がある方は是非お待ちしております。

本ブログでは定期的にこういったテストにまつわる情報をアウトプットをしていきますので、是非本ブログをウォッチして頂ければと思います。

参考文献