BitriseでAndroidライブラリモジュール(AAR)のAndroidTestを実行する
ニッチな需要ではあるが、ライブラリをSDKとして社外に渡す機会があり、BitriseではAndroidライブラリ(AAR)でAndroiTestを実行することができず困っていた。
エラーログと闘った結果、Issueコメントにあったワークアラウンド対応で実行することができたのでメモしておく。
先に結論
Bitriseはライブラリモジュールの【Virtual Device Testing】を想定していないので、【Virtual Device Testing】の【App Path】には適当なダミーAPKを指定する
経緯と詳細
前提条件
- ライブラリモジュールだけ開発しており、アプリケーションモジュールはCI/CDの対象にしてない
- Android OSの機能に依存しており、androidTest配下でしかUnitTestが実行できない(血涙)
解決までの流れ
下記のようなアプリモジュールとライブラリモジュールのシンプルプロジェクトがあったとする。
BitriseAarAndroidTest
├ :app
└ :mylibrary
├ androidTest
│ └ LibrarySampleTest
└ main
└ LibrarySample
LibrarySample
には不届き者が追加したデバックコードが含まれており、AndroidTestでしかUnitTestを実行できない。
import android.os.SystemClock
object LibrarySample {
fun hello(): String {
// FIXME 消して
val start = SystemClock.elapsedRealtime()
val end = SystemClock.elapsedRealtime()
println("time: ${end - start}")
return "Hello"
}
}
LibrarySampleTest
の中身は至って単純。
class LibrarySampleTest {
@Test
fun testHello() {
assert(LibrarySample.hello() == "Hello")
}
}
hello()
がAndroid OSの機能を使っていなければどれだけ良かったことか。と思うが、AndroidStudio上では無論、問題なくテストが通る。通ってしまう。
BitriseでAARのInstrumentationTest
さて、BitriseでAndroidプロジェクトを追加すると、デフォルトで下記のprimary
WorkFlowが作成される
primary:
description: |
Runs tests.
Next steps:
- Check out [Getting started with Android apps](https://devcenter.bitrise.io/en/getting-started/getting-started-with-android-apps.html).
steps:
- activate-ssh-key@4: {}
- git-clone@6: {}
- cache-pull@2: {}
- install-missing-android-tools@3:
inputs:
- gradlew_path: "$PROJECT_LOCATION/gradlew"
- android-unit-test@1:
inputs:
- project_location: "$PROJECT_LOCATION"
- variant: "$VARIANT"
- cache-push@2: {}
- deploy-to-bitrise-io@2: {}
これだと通常のUnitTestしか実行されず、今回作成したLibrarySampleTest
は実行されないので、仮想デバイスによるInstrumentationTestを追加する。
仮想デバイスでテストするにはAndroidTest実行用のapkを作成する必要があるので、android-build-for-ui-testing
も追加しておく。
- android-build-for-ui-testing@0:
inputs:
- variant: debug
- module: mylibrary
- virtual-device-testing-for-android@1:
inputs:
- test_devices: NexusLowRes,30,en,portrait
- test_type: instrumentation
GUIだとこんな感じ。
これで.aar
が生成されて、仮想デバイスでテストしてくれるはず。
実行(1敗)
BUILD SUCCESSFUL in 35s
54 actionable tasks: 40 executed, 14 up-to-date
APKs found after the build:
1. /bitrise/src/mylibrary/build/outputs/apk/androidTest/debug/mylibrary-debug-androidTest.apk
Export APKs:
Export [ mylibrary-debug-androidTest.apk => $BITRISE_DEPLOY_DIR/mylibrary-debug-androidTest.apk ]
Could not find the exported app APK
| |
+---+---------------------------------------------------------------+----------+
| x | Android Build for UI Testing | 37.79 sec |
+---+---------------------------------------------------------------+----------+
| Issue tracker: https://github.com/bitrise-steplib/bitrise-step-android-bu... |
| Source: https://github.com/bitrise-steplib/bitrise-step-android-build-for... |
+---+---------------------------------------------------------------+----------+
しかし、 BUILD SUCCESSFUL と勝利宣言をされているにもかかわらず Could not find the exported app APK とFailure扱いになる。後続の【Virtual Device Testing】はスキップ扱いとなる。
Virtual Device Testingを強制的に実行しても良いが、InstrumentationTestの実行対象は$BITRISE_APK_PATH
なので、拾ってくれるかも怪しい。
し、どの道【Android Build For UI Testing】がコケてるので何とかしたい。
Gradleで無理やりAndroidTest用のAPKを作る
AndroidStudioでは下記のコマンドでライブラリモジュールでもAndroidTest用のAPKを作成できる
./gradlew :mylibrary:assembleDebugAndroidTest
ので、Bitriseから上記のコマンドを実行できるよう、【Android Build For UI Testing】を消して【Gradle Runner】を追加する。
- gradle-runner@2:
inputs:
- gradlew_path: "./gradlew"
- gradle_task: ":mylibrary:assembleDebugAndroidTest"
これで実行すると、
Collecting cache:
Move APK and AAB files...
No file name matched app filters
Copying mylibrary/build/outputs/apk/androidTest/debug/mylibrary-debug-androidTest.apk --> /bitrise/deploy/mylibrary-debug-androidTest.apk
The apk path is now available in the Environment Variable: $BITRISE_TEST_APK_PATH (value: /bitrise/deploy/mylibrary-debug-androidTest.apk)
Move mapping files...
No mapping file matched the filters
AndroidTest用のAPKは$BITRISE_TEST_APK_PATH
に紐づけられるとご丁寧に教えてくれるので、【Virtual Device Testing】を改修する。
- virtual-device-testing-for-android@1:
inputs:
- app_path: "$BITRISE_TEST_APK_PATH"
- test_devices: NexusLowRes,30,en,portrait
- test_type: instrumentation
実行(2敗)
Failed to get test status, error: Failed to get test status: INVALID(TEST_SAME_AS_APP) (exit code: 1) と怒られる
どうも、下記2ヶ所のパスが被ってると怒られるらしい。
- Virtual Device Testing > App Path
- Virtual Device Testing > Instrumentation Test > Test APK Path
AARではAndroidTestでしかAPKを生成できないため、別のApp Pathを指定できない。困った。
適当なダミーAPKを渡す
調べたらIssueが立っており、ワークアラウンドが投稿されていた。
App Pathは要求されているだけでテスト対象じゃないっぽいので、適当なAPKをリポジトリに入れて渡せば良いらしい。
今回は:app
のデバッグ版をビルドしてプロジェクト直下に置いてみた。
BitriseAarAndroidTest
├ :app
└ :mylibrary
│ ├ androidTest
│ │ └ LibrarySampleTest
│ └ main
│ └ LibrarySample
└ dummy.apk // ← NEW!!
【Virtual Device Testing】のapp_path
は直書きである。
- virtual-device-testing-for-android@1:
inputs:
- app_path: "./dummy.apk"
- test_devices: NexusLowRes,30,en,portrait
- test_type: instrumentation
実行(1勝)
無事、 Success やったね!
Discussion