$30 off During Our Annual Pro Sale. View Details »

DroidKaigi 2022: Gradle Managed Virtual Devicesで変化するエミュレータ活用術

TOYAMA Sumio
October 05, 2022

DroidKaigi 2022: Gradle Managed Virtual Devicesで変化するエミュレータ活用術

DroidKaigi 2022のセッション「Gradle Managed Virtual Devicesで変化するエミュレータ活用術」の発表資料です。

新しく導入されたGradle Managed Virtual Devices機能はどのようなものなのか、それによってエミュレータの使い方がどのように変化してくのか紹介します。
また、AGPの実装を調べて判明した内容を元に、Gradle Managed Virtual Devicesを活用する際に直面しがちなトラブルの解決方法も合わせて紹介します。

TOYAMA Sumio

October 05, 2022
Tweet

More Decks by TOYAMA Sumio

Other Decks in Programming

Transcript

  1. Gradle Managed Virtual Devices で変化するエミュレータ活⽤術 2022.10.05 TOYAMA Sumio (sumio_tym) 1

  2. ⾃⼰紹介 p ⽒名: 外⼭ 純⽣ (TOYAMA Sumio) @sumio_tym (Twitter) /

    @sumio (GitHub) p 所属: DeNA SWET第⼆グループ (Software Engineer in Test) p 業務内容: 主にAndroidにおける 品質のボトルネック解決 p その他: 「Androidテスト全書」執筆 https://peaks.cc/sumio_tym/android_testing 2
  3. お話しすること Gradleでエミュレータ作成〜テスト実⾏を実現する Gradle Managed (Virtual) Devices (GMD)について説明します p GMDとはどんな機能? p

    GMDの⽅が便利なのはどんなケース? p GMDで実⾏に失敗したらどうデバッグする? 3 公式な⾔及では「Gradle Managed Virtual Devices」と「Gradle Managed Devices」 の呼称が混在していますが、以降ではAndroid Developersサイトで使われ始めた後者の 呼称を使います
  4. Agenda 1. GMD (Gradle Managed Devices)の使い⽅ 2. Androidエミュレータについておさらい 3. GMDの困るところに対応する

    4. テストの種類別GMD活⽤シーン 5. CIで動かすときのポイント 6. まとめ 4
  5. Agenda 5 1. GMD (Gradle Managed Devices)の使い⽅ 2. Androidエミュレータについておさらい 3.

    GMDの困るところに対応する 4. テストの種類別GMD活⽤シーン 5. CIで動かすときのポイント 6. まとめ
  6. GMD (Gradle Managed Devices)とは p AGP (Android Gradle Plugin)の新機能 p

    7.3.0よりstable (7.2では動かない機能あり) p build.gradleにエミュレータ種別を書いておけば、 AVD作成からテスト実⾏までGradleがやってくれる (AVD: Android Virtual Device) 6 AVD作成 エミュレータ起動 テスト実⾏ アプリ消去 エミュレータ終了 テストレポート作成
  7. (参考) バージョンの関係 p Android Studioも使う場合、Stable版以外ではバージョン 判定がシビアなので注意が必要 7 AGP Gradle (Android

    Studio) 7.2.2 7.3.3+ Chipmunk | 2021.2.1 Patch 2 7.3.0 7.4+ Dolphin | 2021.3.1 7.4.0-beta02 7.5+ Electric Eel | 2022.1.1 Beta 1 8.0.0-alpha02 7.5+ Flamingo | 2022.2.1 Canary 2 ※2022.10.04現在の、メジャーバージョンごとの最新版
  8. build.gradle (デバイスの定義) 8 android { testOptions { managedDevices { devices

    { pixel5api33 (ManagedVirtualDevice) { device = "Pixel 5" apiLevel = 33 systemImageSource = "google" require64Bit = false } ... }}}}
  9. build.gradle (デバイスの定義) 9 android { testOptions { managedDevices { devices

    { pixel5api33 (ManagedVirtualDevice) { device = "Pixel 5" apiLevel = 33 systemImageSource = "google" require64Bit = false } ... }}}} デバイス名(適当な名前をつける) Device Profile システムイメージ x86_64イメージを 強制的に使うかどうか
  10. systemImageSourceに指定できる値 10 従前のシステムイメージ ATD (Automated Test Device) (API Level 30,

    31のみ) 無印(AOSP) "aosp" "aosp-atd" Google APIs "google" "google-atd" Google Play "google_apis_playstore" (AGP 7.3+のみ) N/A ※ATD: Instrumented Test⽤途に最適化された軽量版システムイメージ。 ハードウェアレンダリングが無効化されていたり、 テストで使わなさそうなアプリやサービスが削除・無効化されている ※ATDで削除されているものの詳細は https://d.android.com/studio/test/gradle-managed-devices 参照
  11. build.gradle (複数個のデバイス定義) 11 android { testOptions { managedDevices { devices

    { pixel5api33 (ManagedVirtualDevice) { ... } pixel5api31 (ManagedVirtualDevice) { ... } pixel2api33 (ManagedVirtualDevice) { ... } } }}}
  12. android { testOptions { managedDevices { devices { pixel5api33 (ManagedVirtualDevice)

    { ... } pixel5api31 (ManagedVirtualDevice) { ... } pixel2api33 (ManagedVirtualDevice) { ... } } }}} build.gradle (複数個のデバイス定義) 12 複数個のデバイス定義を宣⾔できる
  13. build.gradle (デバイスグループ) 13 devices { pixel5api33 (ManagedVirtualDevice) { ... }

    pixel5api31 (ManagedVirtualDevice) { ... } pixel2api33 (ManagedVirtualDevice) { ... } } deviceGroups { pixel5 { targetDevices.add(devices.pixel5api33) targetDevices.add(devices.pixel5api31) } } }
  14. build.gradle (デバイスグループ) 14 devices { pixel5api33 (ManagedVirtualDevice) { ... }

    pixel5api31 (ManagedVirtualDevice) { ... } pixel2api33 (ManagedVirtualDevice) { ... } } deviceGroups { pixel5 { targetDevices.add(devices.pixel5api33) targetDevices.add(devices.pixel5api31) } } } デバイスグループ名 (適当な名前を付ける)
  15. 新しく作られるGradleタスク(基本的なもの) p pixel5api33DebugAndroidTest ( {デバイス名}{バリアント}AndroidTest ) p {デバイス名}に対応するエミュレータを起動し、 Instrumented Testを実⾏する

    p pixel5GroupDebugAndroidTest ( {デバイスグループ名}Group{バリアント}AndroidTest ) p {デバイスグループ名}の各デバイスについて、対応するエミュレー タを起動し、Instrumented Testを実⾏する 15
  16. 新しく作られるGradleタスク(その他①) p pixel5api33Setup ( {デバイス名}Setup ) p {デバイス名}に対応するAVDが無ければ新しく作り、 起動⾼速化のためにSnapshot(エミュレータのメモリなど)を保存する p

    {デバイス名}{バリアント}AndroidTestなどテスト実⾏時に呼ばれる p 時々このタスクだけ実⾏したくなることがある p cleanManagedDevices p この仕組みで作られたAVDを全部消す p 実⾏注意!! 16
  17. 新しく作られるGradleタスク (その他②) p allDevicesDebugAndroidTest p build.gradleで宣⾔された全AVDについてテストする p デバイスグループを宣⾔しなくても使える p createManagedDeviceDebugAndroidTestCoverageReport

    p 全AVDについてテスト → カバレッジレポート出⼒ (設定 testCoverageEnabled true が必要) 17
  18. テストレポート・ログ p app/build/outputs/androidTest-results/managedDevice/ flavors/{フレーバー名}/{デバイス名}/ p JUnit互換テスト結果XML p ログ (logcat・adbなどの実⾏コマンドログ) p

    app/build/reports/androidTests/managedDevice/ flavors/{フレーバー名}/{デバイス名}/ p HTML形式のテスト結果レポート 18
  19. AVDの保存場所 GMDが作るAVDは隠されている p Android StudioのDevice Managerで作るAVD: $HOME/.android/avd/ p GMDが作るAVD (AGP

    7.3+): $HOME/.android/avd/gradle-managed p GMDが作るAVD (AGP 7.2.x): $HOME/.android/gradle/avd/ 19
  20. ここまでのまとめ p AVD作成時に指定できる項⽬は多くない。 Device Profile、APIレベル、システムイメージのみ p 複数のAVDに対して、まとめてテストできる機能がある (デバイスグループ) p AVD作成→エミュレータ起動→テスト実⾏→レポート作成

    までいっぺんに実⾏するGradleタスクが使えるようになる p GMDによって作られたAVDは隠されている 20
  21. GMDの嬉しいところ p build.gradleに書けばGradleが全部やってくれる p AVDの作成をGUIで操作しなくてOK p エミュレータ使ったテストのCI上での実⾏が簡単に p avdmanager create

    avdとか知らなくてOK p エミュレータの起動・終了を管理しなくてOK p adb wait-for-deviceなど・・ 21
  22. GMDの困るところ p テスト実⾏中の画⾯が⾒えない p アプリが起動しているかどうかすら分からない p AVD作成時のカスタマイズ項⽬が貧弱 p せめて⽇本語の環境で動かしたい p

    RAMサイズ、ストレージサイズくらいは変更したい! p テストが終わるとapkがアンインストールされる p テスト実⾏中に作られたファイルも消えてしまう・・ p テストに失敗したときのデバッグが難しい 22
  23. 困るところは⾊々あるけれど・・・ p いくつかの点は運⽤を⼯夫することで解決できる p ⼯夫のためにはAndroidエミュレータについて 少し深い知識が必要 詳しい説明の前に Androidエミュレータについて少しおさらいします 23

  24. Agenda 24 1. GMD (Gradle Managed Devices)の使い⽅ 2. Androidエミュレータについておさらい 3.

    GMDの困るところに対応する 4. テストの種類別GMD活⽤シーン 5. CIで動かすときのポイント 6. まとめ
  25. 普段の開発で利⽤しているエミュレータ Android StudioのDevice ManagerからAVDを選んで起動 25

  26. CLIでエミュレータを起動する① p コマンドの場所 $ANDROID_HOME/emulator/emulator ($ANDROID_HOME/tools/emulatorは使わない) 26

  27. CLIでエミュレータを起動する② p AVD名⼀覧表⽰ emulator -list-avds p AVD名を指定してエミュレータ起動 emulator -avd {AVD名}

    27 この⽅法で表⽰・起動できるのは Android Studioで作ったAVDのみ ($HOME/.android/avd/に保存されているもの)
  28. CLIでエミュレータを起動する③ 環境変数ANDROID_AVD_HOMEで AVDの保存・検索ディレクトリを変更できる p {AVD保存場所}にあるAVD名の⼀覧表⽰ env ANDROID_AVD_HOME={AVD保存場所} emulator -list-avds p

    {AVD保存場所}にあるAVD名を指定してエミュレータ起動 env ANDROID_AVD_HOME={AVD保存場所} emulator –avd {AVD名} 28
  29. AVDのファイル構成 (主要なもののみ) 29 ├── Pixel_3a_API_29.avd/ │ ├── hardware-qemu.ini │ ├──

    config.ini │ ├── encryptionkey.img, encryptionkey.img.qcow2 │ ├── cache.img, cache.img.qcow2 │ ├── userdata-qemu.img, userdata-qemu.img.qcow2 │ ├── userdata.img │ ├── ... └── Pixel_3a_API_29.ini ハードウェア・AVDの設定 ディスクイメージ
  30. ここまでのまとめ p emulatorコマンドでCLIでもエミュレータを起動できる p コマンドサーチパス間違わないように注意 p 環境変数ANDROID_AVD_HOMEを設定すれば 標準以外の場所に保存されたAVDも参照できる p 保存されたAVDには、AVDの設定内容やディスクイメージ

    が格納されている 30
  31. Agenda 31 1. GMD (Gradle Managed Devices)の使い⽅ 2. Androidエミュレータについておさらい 3.

    GMDの困るところに対応する 4. テストの種類別GMD活⽤シーン 5. CIで動かすときのポイント 6. まとめ
  32. GMDの困るところ (再掲) 32 p テスト実⾏中の画⾯が⾒えない p アプリが起動しているかどうかすら分からない p AVD作成時のカスタマイズ項⽬が貧弱 p

    せめて⽇本語の環境で動かしたい p RAMサイズ、ストレージサイズくらいは変更したい! p テストが終わるとapkがアンインストールされる p テスト実⾏中に作られたファイルも消えてしまう・・ p テストに失敗したときのデバッグが難しい
  33. 困り事の解決① 33 p テスト実⾏中の画⾯が⾒えない p アプリが起動しているかどうかすら分からない 画⾯を表⽰しながら テストを実⾏する

  34. 画⾯を表⽰しながらテストを実⾏する p --enable-displayオプションを使う p 知っておくと便利なコマンド p Gradleタスクに使えるオプションがわかる ./gradlew -q help

    --task {タスク名} 34 ./gradlew pixel5api33DebugAndroidTest --enable-display
  35. 困り事の解決② 35 p AVD作成時のカスタマイズ項⽬が貧弱 p せめて⽇本語の環境で動かしたい 別アプリの助けを借りて ⾔語設定を変更する

  36. 別アプリの助けを借りて⾔語設定を変更する ① io.appium.settingsを使う(https://github.com/appium/io.appium.settings) p インストール(npm) npm i io.appium.settings p app/build.gradle

    36 dependencies { androidTestUtil files('../node_modules/io.appium.settings/apks/settings _apk-debug.apk') } テスト実⾏時に、指定されたapkを パーミッションをgrantした状態で インストールしてくれる
  37. 別アプリの助けを借りて⾔語設定を変更する ② 37 class LocaleChangeListener : RunListener() { override fun

    testRunStarted(desc: Description?) { val uiAutomation = InstrumentationRegistry.getInstrumentation().uiAutomation val fd = uiAutomation.executeShellCommand("...") // 標準出⼒を全部捨てる }} p JUnit4のRunListenerを使って最初のテスト開始前に以下を実⾏する am broadcast -a io.appium.settings.locale -n io.appium.settings/.receivers.LocaleSettingReceiver --es lang {⾔語} --es country {地域}
  38. 別アプリの助けを借りて⾔語設定を変更する ② 38 class LocaleChangeListener : RunListener() { override fun

    testRunStarted(desc: Description?) { val uiAutomation = InstrumentationRegistry.getInstrumentation().uiAutomation val fd = uiAutomation.executeShellCommand("...") // 標準出⼒を全部捨てる }} p JUnit4のRunListenerを使って最初のテスト開始前に以下を実⾏する am broadcast -a io.appium.settings.locale -n io.appium.settings/.receivers.LocaleSettingReceiver --es lang {⾔語} --es country {地域}
  39. 別アプリの助けを借りて⾔語設定を変更する ② 39 class LocaleChangeListener : RunListener() { override fun

    testRunStarted(desc: Description?) { val uiAutomation = InstrumentationRegistry.getInstrumentation().uiAutomation val fd = uiAutomation.executeShellCommand("...") // 標準出⼒を全部捨てる }} テストコードから シェルコマンドを実⾏できる p JUnit4のRunListenerを使って最初のテスト開始前に以下を実⾏する am broadcast -a io.appium.settings.locale -n io.appium.settings/.receivers.LocaleSettingReceiver --es lang {⾔語} --es country {地域}
  40. 別アプリの助けを借りて⾔語設定を変更する ③ p build.gradleでRunListener実装を登録する 40 android { defaultConfig { testInstrumentationRunnerArgument(

    "listener", "com.example.gmd.LocaleChangeListener" ) } } • RunListener実装のクラス名を書く • 複数登録する場合はコンマ(,)区切り
  41. 困り事の解決③ 41 p AVD作成時のカスタマイズ項⽬が貧弱 p RAMサイズ、ストレージサイズくらいは変更したい! GMDで作られた AVDの設定を変える

  42. GMDで作られたAVDの設定を変える p GMDで作られたAVDのconfig.iniなどを変更する 場所: $HOME/.android/avd/gradle-managed/{AVD名}.avd/ p ディスクサイズ変更: disk.dataPartition.size=6g (config.ini) p

    etc. p 何を変更すれば良いか知りたいとき p hardware-properties.iniに詳しく定義されている https://bit.ly/3SXgisv (android.googlesource.com) 42
  43. 困り事の解決④ 43 p テストが終わるとapkがアンインストールされる p テスト実⾏中に作られたファイルも消えてしまう・・ テスト終了時にファイル を取り出す

  44. テスト終了時にファイルを取り出す① p 隠しオプションadditionalTestOutputDirを使う 44 android { defaultConfig { testInstrumentationRunnerArgument( "additionalTestOutputDir",

    "/sdcard/Android/media/com.example.gmd/result" ) } } ファイルを取り出したい (エミュレータ上の)ディレクトリ
  45. テスト終了時にファイルを取り出す② p 取り出された(pullされた)ファイルの保存先 p AGP 8.0未満: app/build/outputs/ managed_device_android_test_additional_output p AGP

    8.0以上: app/build/intermediates/ managed_device_android_test_additional_output p 引数に指定できるディレクトリについての注意 p Scoped Storageが有効なOSでは /sdcard/Android/media/{アプリケーションID}/ から始まるディレクトリしか受け付けない (それ以外に保存されたファイルは取り出せない) 45
  46. 困り事の解決⑤ 46 p テストが終わるとapkがアンインストールされる p テストに失敗したときのデバッグが難しい 予めエミュレータを起動した 状態でテストを動かす

  47. エミュレータを起動した状態でテストを動かす① p 予めGMDが作成したAVDでエミュレータを起動しておく env ANDROID_AVD_HOME=$HOME/.android/avd/gradle-managed emulator –avd {AVD名} p より正確に再現したいときは、以下のファイルを参考に

    emulatorコマンドのオプションを付ける (GMDでエミュレータを起動したときの環境変数や コマンドラインオプションなどが記録されている) app/build/outputs/androidTest-results/ managedDevice/(省略)/emulator.1.ok.txt 47
  48. (参考) emulator.1.ok.txtの例 48 EXECUTING: /usr/local/Caskroom/android- sdk/4333796/emulator/emulator @dev31_default_x86_64_Pixel_5 - no-window -no-audio

    -gpu auto-no-window -read-only -no-boot- anim -id :app:pixel5api31aospDebugAndroidTest CURRENT_WORKING_DIRECTORY: ... START_TIME: ... ENVIRONMENT: ... ANDROID_AVD_HOME=/Users/sumio.toyama/.android/avd/gradle- managed ***************************************** STDOUT/STDERR BELOW
  49. エミュレータを起動した状態でテストを動かす② p Android Studioや ./gradlew connected{バリアント}AndroidTest などで通常通りテストを実⾏してデバッグする p テストが終了しても勝⼿にファイルが消えない p

    デバッグ実⾏も可能 49
  50. その他のTips: テストの録画(テスト全体を1ファイルに録画) p JUnit4のRunListenerを使って、初回のテスト開始前に screenrecordコマンドを実⾏する p 標準出⼒をreadしなければコマンド終了を待たずに先に進める p 全テスト終了時(RunListener.testRunFinished())に 実⾏中のscreenrecordコマンドをkillする

    p "pidof screenrecord" でpidを探す p 探したpidに対して"kill –INT $pid" p 録画したmp4はadditionalTestOutputDirで取り出す 参考: JUnit Test Ruleとしての実装サンプル ScreenRecordRule.kt https://gist.github.com/mkeeda/30b8cfdcec53859a2cd39cac36d7fc9e 50
  51. その他のTips: そのほか① p エミュレータの状態がおかしいので⼀度Cold Bootしたい p GMDが作成したAVDでエミュレータを起動する⽅法を使って、 -no-snapshot-loadオプションを付けて起動・終了する p エミュレータをキッティングしておきたい

    (Googleアカウントログインなど) p ./gradlew {デバイス名}Setup で、GMDにAVDだけ作成させる p そのAVDでエミュレータを起動し、必要な操作を⾏って終了する 51
  52. その他のTips: そのほか② p (デバイスグループなど)複数のAVDをまとめてテストする と結果が不安定になる問題を解決したい p GMDインスタンス数の並列度を下げる(AGP 7.4+) -Pandroid.experimental.testOptions.managedDevices .maxConcurrentDevices=1

    p Gradleタスクの並列度を下げる -Dorg.gradle.workers.max=1 p 事前にpackageDebugAndroidTestで並列にビルドしておき、 テストだけ本オプションを付けるのがおすすめ 52
  53. これらの⼯夫でも対応できないこと p エミュレータ起動時のコマンドラインオプションを カスタマイズできない (とはいえconfig.iniでも指定できる項⽬が多い) p (エミュレータ起動中の) テスト開始直前・終了直後に処理を挟み込めない p JUnit4のRunListenerとexecuteShellCommandを使えば

    テスト開始直前・終了直後にshellコマンドの実⾏は可能 53
  54. ここまでのまとめ p 以下の⼿段で、困りごとは概ね解決できる p --enable-displayオプション p config.iniのカスタマイズ p ANDROID_AVD_HOME環境変数を指定した エミュレータ起動

    p JUnit4のRunListenerで最初のテスト開始前にシェルコマンド発⾏ p エミュレータ起動時のオプションを変更したり、 テスト実⾏前後に任意の処理を挟み込むのは難しい 54
  55. Agenda 55 1. GMD (Gradle Managed Devices)の使い⽅ 2. Androidエミュレータについておさらい 3.

    GMDの困るところに対応する 4. テストの種類別GMD活⽤シーン 5. CIで動かすときのポイント 6. まとめ
  56. テストの種類別GMD活⽤シーン 1. Robolectricが必要なLocal Testの移⾏ 2. UIテスト 3. スクリーンショットテスト 56

  57. Robolectricが必要なLocal Testの移⾏① エミュレータ(GMD)で動かせばテスト忠実度は確実に上がる p Roblectricのバージョンアップ対応⼯数をゼロにできる p GMDへの移⾏は⽐較的容易なはず p src/test から

    src/androidTestへ移動 (src/sharedTest はChipmunkから使えなくなった) p Robolectric固有のアノテーション(@Configなど)の削除 p AVDのカスタマイズが必要なケースは少ないはず p 軽量なATD (Automated Test Device)でも動作するはず 57
  58. Robolectricが必要なLocal Testの移⾏② p GMD (ATD)に移⾏した場合のテスト実⾏時間は? p 1テストクラス、18テストケースで計測 p iMac Pro

    2017 3.2GHz Xeon 8コア、32GB RAM 58 Robolectric GMD (ATD) テストクラス初回ロード 6〜15sec 0.6〜0.7sec エミュレータ起動 0sec 40〜60sec テスト実⾏時間 (初回ロード以外) 0.900〜1.000sec 0.200〜0.300sec
  59. Robolectricが必要なLocal Testの移⾏② p エミュレータの起動はとても遅い p 個々のテスト実⾏時間はエミュレータが3倍程度速い p 該当するテストが⼤量にあれば時間的にもペイするかも??? p 忠実度とメンテナンス性を期待してGMDに移⾏するのは⼀案

    59 Robolectric GMD (ATD) テストクラス初回ロード 6〜15sec 0.6〜0.7sec エミュレータ起動 0sec 40〜60sec テスト実⾏時間 (初回ロード以外) 0.900〜1.000sec 0.200〜0.300sec
  60. UIテスト p AVDのカスタマイズ無しに動くテストはGMDで p 環境差異による不安定なテストを減らせる p 軽量版でない⽅のGMDを使うのが無難 p 軽量のATD (Automated

    Test Device)では画⾯表⽰不可 p UIテストで使えるTips p 画⾯を⾒ながら動かす: --enable-displayオプション p ⾔語設定を英語以外にしたい: io.appium.settingsアプリ 60
  61. スクリーンショットテスト p 判断基準やTipsはUIテストと同じ p 軽量版でない⽅のGMDが無難 p ATDで使えるスクリーンショットはCanvasにView.draw()する⽅式のみ p スクリーンショット保存先に注意 p

    /sdcard/Android/media/{アプリケーションID}/ から始まるディレクトリに保存する p 保存したスクリーンショットはadditionalTestOutputDir オプションを使って取り出す 61
  62. GMDが使えるシーンまとめ p Robolectricが必要なLocal Test p ⾼速化は期待できないが忠実度とメンテナンス性に期待 p UIテストやスクリーンショットテスト p AVDのカスタマイズ無しに動くものなら利⽤できる

    ただし・・・ CIでもGMDが動かないと効果半減なことに注意 62
  63. Agenda 63 1. GMD (Gradle Managed Devices)の使い⽅ 2. Androidエミュレータについておさらい 3.

    GMDの困るところに対応する 4. テストの種類別GMD活⽤シーン 5. CIで動かすときのポイント 6. まとめ
  64. CI環境でGMDを使う前に意識したいこと 既に⽤意されているStep・Actionなどは GMDよりカスタマイズできる項⽬が多い p カスタマイズが必要なら既存の⽅法にとどまった⽅が楽 p Bitrise: AVD Manager Step・Wait

    for Android emulator Step https://devcenter.bitrise.io/en/steps-and-workflows/workflow-recipes-for-android-apps/- android--run-tests-using-the-emulator.html p CircleCI: Android Orbの android/start-emulator-and-run-tests Step https://circleci.com/docs/ja/android-machine-image p GitHub Actions: malinskiy/action-android/emulator-run-cmd https://github.com/Malinskiy/action-android p Jenkins: Android Emulator Plugin https://github.com/jenkinsci/android-emulator-plugin 64
  65. ポイント1: エミュレータが動作するか確認する p 仮想環境ではNested Virtualizationが必要 p CircleCIではマシンイメージを使う(Dockerイメージ不可) p エミュレータが動く潤沢なRAMが必要 p

    Gradleの消費メモリも考えると8GBでは⾜りない p 既存のエミュレータ利⽤に関する設定例を参考にする p Bitrise: 情報なし(⼿許ではAndroid & Docker, on Ubuntu 20.04で動作) p CircleCI: androidマシンイメージ (Linux Large) p GitHub Actions: macOS-10.15 65
  66. ポイント2: 必要に応じてGradleオプションを付ける p headless環境(画⾯を表⽰できない環境)のとき -Pandroid.testoptions.manageddevices.emulator.gpu="swiftshader_indirect" p AVDのSetupタスクがタイムアウトするとき -Pandroid.experimental.testOptions.managedDevices.setupTimeoutMinutes でタイムアウト時間を増やす (Minutesは誤記。正しくは秒)

    66 (参考) SunflowerアプリのGitHub Actions設定 https://github.com/android/sunflower/pull/785
  67. ポイント3: テスト失敗時の解析をやりやすくする p ログファイルをArtifactsに保存しておく app/build/outputs/androidTest-results/** p テストを録画し、動画ファイルをArtifactsに保存しておく (「その他のTips: テストの録画」参照) p

    実⾏時ログをより詳しくするGradleオプションを付ける p --info p -Pandroid.experimental.testOptions.managedDevices.emulator.showKernelLogging=true 67 (参考) SunflowerアプリのGitHub Actions設定 https://github.com/android/sunflower/pull/785
  68. GMDでAVDをカスタマイズしたいとき① ビルド間で実⾏環境を保持できるケースでは容易 (⾃前で調達したJenkinsビルドマシンなど) 1. 事前に{デバイス名}SetupタスクでAVD作成 2. 作ったAVDでエミュレータを起動してキッティング 3. エミュレータ終了でディスクイメージが保存される 4.

    以降、GMDのテストタスク実⾏でキッティングしたAVDが 利⽤される 68
  69. GMDでAVDをカスタマイズしたいとき② ビルド毎に実⾏環境が作り直されるサービスでは難しいが、、 (CircleCI、Bitrise、GitHub ActionsのGitHub-hosted runnerなど) p AVDのconfig.iniの書き換えで済む範囲なら可能 (ディスクサイズ、RAMサイズの増加など) 1. {デバイス名}SetupタスクでAVDを作る

    2. (sedコマンドなどで)作られたAVD内のconfig.iniを書き換える 3. GMDのテストタスクを実⾏する 69
  70. GMDでAVDをカスタマイズしたいとき③ p ディスクイメージのカスタマイズは⼒技が必要 1. ⼿許のマシンで{デバイス名}SetupタスクでAVDを作る 2. 作ったAVDでエミュレータ起動・キッティング(Apple Siliconは未確認) 3. AVD内の以下のディスクイメージをGitHubリポジトリなどに保存

    (数GBになるので注意。LFS推奨) p userdata-qemu.img.qcow2 p encryptionkey.img.qcow2 p 状況によっては他のイメージファイルも必要かも知れない 4. config.ini書き換えの要領でディスクイメージを差し替える 70
  71. ここまでのまとめ p 本当にGMD使った⽅が良いか考える p AVDのカスタマイズが必要なら敢えてとどまる選択肢も p ポイントは3つ p エミュレータが起動できる環境を⽤意する p

    必要に応じてGradleオプションを付ける p テスト失敗時の解析をやりやすくする p GMDでAVDをカスタマイズする場合は程々に・・ 71
  72. Agenda 72 1. GMD (Gradle Managed Devices)の使い⽅ 2. Androidエミュレータについておさらい 3.

    GMDの困るところに対応する 4. テストの種類別GMD活⽤シーン 5. CIで動かすときのポイント 6. まとめ
  73. p Gradle Managed Device (GMD) の設定⽅法、使い ⽅、⾜りない点を補う⽅法について説明しました p この内容でかなりのことが出来るようになるはずです p

    テストの種類別にGMDを使うと便利なケース、 そうでないケースを説明しました p GMD活⽤の前提となる CIで動かすときのポイントもあわせて紹介しました 73
  74. 参考URL① p 公式ドキュメント https://d.android.com/studio/test/gradle-managed-devices p Android Code Search (Gradleのオプションが定義されている場所) https://bit.ly/3rrFZp8

    (cs.android.com) p Android Sunflower with Compose (GitHub Actions設定例) https://github.com/android/sunflower p Appiumのio.appium.settingsアプリ https://github.com/appium/io.appium.settings p GitHub Gist: mkeeda/ScreenRecordRule.kt https://gist.github.com/mkeeda/30b8cfdcec53859a2cd39cac36d7fc9e 74
  75. 参考URL② p tkmnzm 「Androidのテストで利⽤できるスクリーンショット取得APIのまとめ」 https://qiita.com/tkmnzm/items/c25c43a8bac07bb90dfb p Bitrise「(Android) Run tests using

    the emulator」 https://bit.ly/3Csu3K5 (devcenter.bitrise.io) p CircleCI「AndroidイメージのMachine Executorでの使⽤」 https://circleci.com/docs/ja/android-machine-image p GitHub Actions: action-android https://github.com/Malinskiy/action-android p Android Emulator Plugin for Jenkins https://github.com/jenkinsci/android-emulator-plugin 75
  76. この発表を参考に Gradle Managed Virtual Devicesを使った エミュレータ上でのテストを 試してみてください ありがとうございました! 76