Posted at

Android JetpackのApp Crawlerを動かしてみる

Shibuya.apk #36ひっそりJetpackに追加されていたApp Crawler toolの紹介 で紹介されていた App Crawler を手元で動かしてみたので、実行方法や、はまったことなどをシェアします。


App Crawlerとは

App Crawlerは、テストコードなしで、自動でUIテストを実行してくれるテストツールです。Firebase Test LabのRobo Testで使われているツールが、おそらくほぼそのまま提供されています。詳しくは、ひっそりJetpackに追加されていたApp Crawler toolの紹介によくまとまっていますので、そちらをご参照ください。

2019年8月8日現在、App Crawlerはまだ正式リリースではなく、Beta 1.0という扱いのようです。App Crawlerの配布ZIPに含まれているREADMEにバージョンとリリースノートが記述されています。


実行方法

App Crawlerは実行可能Jarとして提供されています。公式ドキュメントにある通り、配布されているZIPをダウンロードして、そこに含まれている crawl_launcher.jarjava コマンドで起動することで実行できます。

# ZIPファイルをダウンロードして展開

wget https://dl.google.com/appcrawler/beta1/app-crawler.zip
unzip app-crawler.zip

# java コマンドで実行
java -jar app-crawler/crawl_launcher.jar <他にもいくつかオプションが必要>

なお、App Crawlerを実行するときには、テストを実行するデバイス (エミュレーターでも可) がADBで接続している必要があります。


必須のコマンドラインオプション

公式ドキュメントのCrawler optionsセクションに書いてあるように、App Crawlerの実行時には「Android SDKのパス」と「テスト対象のアプリ」を最低限、コマンドラインオプションで指示する必要があります。


Android SDKのパス

--android-sdk オプションで指定します。

# --android-sdk オプションの例 (Macの場合)

java -jar app-crawler/crawl_launcher.jar --android-sdk ~/Library/Android/sdk <他にもオプションが必要>


テスト対象アプリ

以下のどちらかの方法で、テスト対象のアプリを指定します。


  1. APKファイルが手元にあるアプリを、デバイスにインストールしてテストする

    --apk-file オプションでAPKファイルのパスを指定する

  2. デバイスにインストール済みのアプリをテストする (APKファイルは不要)

    --app-package-name オプションでパッケージ名を指定する

以下は、筆者が Android Architecture Blueprints v2 で試した場合のコマンド例です。

# APKファイルをインストールしてテストする場合の例

java -jar app-crawler/crawl_launcher.jar --android-sdk ~/Library/Android/sdk --apk-file ~/Work/android/android-architecture/app/build/outputs/apk/prod/debug/app-prod-debug.apk

# インストール済みのアプリをテストする場合の例
java -jar app-crawler/crawl_launcher.jar --android-sdk ~/Library/Android/sdk --app-package-name com.example.android.architecture.blueprints.master


テスト結果の出力

テスト結果は、crawl_output というディレクトリの中にファイルで出力されます。crawl_output 内には、例えば、次のようなファイルが生成されます。

crawl_output/

├── com.example.android.architecture.blueprints.master-logcat.txt
└── app_firebase_test_lab/
   ├── 1.png
   ├── 2.png
   ├── 3.png
   ├── accessibility1.meta
   ├── accessibility2.meta
   ├── accessibility3.meta
   ├── crawl_outputs.proto
   ├── crawl_outputs.txt
   ├── robo_actions.dpb
   ├── robo_crawls.dpb
   ├── robo_screen_elements.dpb
   └── robo_screens.dpb

.txt, .png 以外の拡張子のファイルはバイナリファイルで、少なくとも筆者は、バイナリの内容はわかりませんでした。今のところ、テスト実行中のlogcat出力 (*-logcat.txt) と、アプリのスクリーンショット (*.png) が、利用可能なテスト出力と言えそうです。

また、テスト実行中にアプリがクラッシュした場合は、テストがそこで中断し、コンソール出力にスタックトレースが出力されます。


筆者がはまった点

App Crawlerの実行にあたって、筆者がはまったポイントを紹介しておきます。


はまりポイント(1): 古いプラットフォームがSDKにインストールされていると起動に失敗する

Android SDKにAPIレベル9 (Android 2.3) 以下のプラットフォームがインストールされていると、App Crawlerの実行に失敗します。

もっと正確に言うと、Android SDKの platforms ディレクトリ内に、android-7android-8android-9 といったディレクトリがあると、実行に失敗します。


実行に失敗する理由

App Crawlerは、テストの実行前に、App Crawlerの処理をデバイス上で担うAPKをビルドしてデバイスにインストールする、という処理を行なっており、APKのビルドに、Android SDKにインストールされている最新のプラットフォームの android.jar を利用しています。

App Crawlerは、android.jar のパスを得るために「Android SDKにインストールされている最新プラットフォーム」のディレクトリを探すのですが、その処理が単純で、



  1. platforms ディレクトリ内に存在するディレクトリを名前の辞書順に並べて、

  2. 最後になったものを最新のプラットフォームのディレクトリとしている

ようです。

本当なら android-29 などがヒットして欲しいのですが、android-7android-8 などのディレクトリが存在していると、そちらがヒットしてしまい、その中の android.jar がApp Crawler APKのビルドに使われることになります。App CrawlerはminSdkVersion = 18 のアプリなので、APIレベル10未満の android.jar ではビルドができず、結果、テストの実行に失敗する、というわけです。


はまりポイント(2): 最近のOSバージョン上でないと実行できない?

App Crawlerの実行APKは minSdkVersion = 18 なので、Android 4.3 (APIレベル18) 以上のデバイスであれば実行できそうなのですが、筆者が手元で確認した限りでは、Android 7.0 (APIレベル24) 以上のデバイスでないとApp Crawlerが期待通りに動作しませんでした。テスト対象のアプリは起動してApp Crawlerが動きかけるのですが、テストの実行が即座に終了してしまいました。

App Crawlerはエラー検出 & エラー出力の実装がまだ不十分なようで、上記のケースでも特にエラーが出力されず、正常に終了したように見えています。何が悪いのかよくわかっていません。