技術・開発

【GitLab CI/CD】GitLab RunnerでAndroidアプリのJUnitテストを自動化する.gitlab-ci.ymlの設定

2020年7月4日

GitLabには強力なCI/CD機能が標準で実装されています。
今回はこの機能(GitLab Runner)を利用して、AndroidアプリのビルドからJUnitテストの実行、テスト結果のレポート出力までを自動化してみました。

.gitlab-ci.yml の設定例

プロジェクトのルートディレクトリに配置する .gitlab-ci.yml のコードは以下の通りです。

image: openjdk:8-jdk

variables:
  ANDROID_COMPILE_SDK: "29"
  ANDROID_BUILD_TOOLS: "29.0.2"
  ANDROID_SDK_TOOLS:   "6200805"

before_script:
  - apt-get --quiet update --yes
  - apt-get --quiet install --yes wget tar unzip lib32stdc++6 lib32z1
  - wget --quiet --output-document=android-sdk.zip https://dl.google.com/android/repository/commandlinetools-linux-${ANDROID_SDK_TOOLS}_latest.zip
  - unzip -d android-sdk-linux android-sdk.zip
  - mkdir -p android-sdk-linux/licenses/
  - echo "8933bad161af4178b1185d1a37fbf41ea5269c55nd56f5187479451eabf01fb78af6dfcb131a6481en24333f8a63b6825ea9c5514f83c2829b004d1fee" > android-sdk-linux/licenses/android-sdk-license
  - echo "84831b9409646a918e30573bab4c9c91346d8abdn504667f4c0de7af1a06de9f4b1727b84351f2910" > android-sdk-linux/licenses/android-sdk-preview-license
  - echo y | android-sdk-linux/tools/bin/sdkmanager --sdk_root=android-sdk-linux --licenses > /dev/null
  - echo y | android-sdk-linux/tools/bin/sdkmanager --sdk_root=android-sdk-linux "platforms;android-${ANDROID_COMPILE_SDK}" >/dev/null
  - echo y | android-sdk-linux/tools/bin/sdkmanager --sdk_root=android-sdk-linux "platform-tools" >/dev/null
  - echo y | android-sdk-linux/tools/bin/sdkmanager --sdk_root=android-sdk-linux "build-tools;${ANDROID_BUILD_TOOLS}" >/dev/null
  - export ANDROID_HOME=$PWD/android-sdk-linux
  - export PATH=$PATH:$PWD/android-sdk-linux/platform-tools/
  - chmod +x ./gradlew
  # temporarily disable checking for EPIPE error and use yes to accept all licenses
  - set +o pipefail
  - yes | android-sdk-linux/tools/bin/sdkmanager --sdk_root=android-sdk-linux --licenses
  - yes | android-sdk-linux/tools/bin/sdkmanager --sdk_root=android-sdk-linux --update
  - set -o pipefail

lintDebug:
  stage: build
  script:
    - ./gradlew -Pci --console=plain :app:lintDebug -PbuildDir=lint

assembleDebug:
  stage: build
  script:
    - ./gradlew assembleDebug
  artifacts:
    paths:
    - app/build/outputs/

debugTests:
  stage: test
  script:
    - ./gradlew -Pci --console=plain :app:testDebug

unitTests:
  stage: test
  script:
    - ./gradlew testDebugUnitTest 
  artifacts:
    paths:
      - app/build/reports/tests/testDebugUnitTest/

設定コードの解説とポイント

1. Variables と before_script(Android SDKの準備)

ベースとなるDockerイメージには openjdk:8-jdk を使用しています。

variables の部分で、ビルド対象となるAndroid SDKのバージョンやビルドツール群のバージョンを一括管理しています。
before_script では、コンテナ内にAndroid SDKをダウンロードしてインストールしています。以前と比べてSDKのURLやインストール手順(commandlinetools の利用など)が変わっているため、古いやり方のままだとエラーになってしまうので注意が必要です。

また、スクリプト内の14〜15行目や26〜27行目で、Android SDKのライセンスに自動同意するための記述(yes | ... やハッシュ値のecho)を行っています。重複している部分もあるため、環境によっては14〜15行目は省略しても問題ないかもしれません。

2. テストの実行と artifacts(成果物の保存)

33行目以降の stage: test から、実際にLintチェックやJUnitテストを実施するコマンドが走ります。

CI/CD実行後に成果物(ビルドされたAPKやテストレポート)を保存して画面上からダウンロードしたい場合は、以下のように artifactspaths を指定します。

artifacts:
    paths:
      - app/build/reports/tests/testDebugUnitTest/

これにより、GitLabのパイプライン結果画面からJUnitの実行レポート(HTML等)を直接閲覧・取得できるようになります。

GitLabに保存されたJUnitテストの実行結果レポート画面

運用時の注意点・所感(ビルド時間の短縮について)

GitLab.comなどが提供する「共有Runner」を使用する場合、ジョブが走るたびに毎回まっさらなコンテナが立ち上がります。 そのため、今回の設定のように before_script で「Android SDKのダウンロードとインストール」から始めなければならず、これだけで毎回数分のタイムロスが発生し、全体的に処理が遅くなってしまいます。

もし自前のサーバー(Specific Runner)を用意できる環境や、Dockerイメージを自作できる環境であれば、あらかじめAndroid SDK一式がインストール済みのカスタムコンテナイメージを作成・利用したほうが、CI/CDの実行時間は劇的に早くなると思います。

-技術・開発
-, , , , , , ,