Android の Instrumented Test で指定のサイズのテストだけ実行する (@SmallTest とか @LargeTest とか)
Android Testing Support Library (ATSL) の話。 バージョン 0.5 時点での情報です。
ライブラリの準備方法などはドキュメントを読んでください。
テストサイズを表すアノテーション
android.support.test.filters
というパッケージがあって、この中にはテストをフィルタするのに使用できるアノテーションが入っています。 その中に、テストのサイズを表すためのアノテーションが 3 つ入っています。
@SmallTest
アノテーション : 200 ms 未満で終わるようなテスト。 ほぼユニットテスト用。 各種リソース (ファイルや DB、ネットワーク) は使用しない。@MediumTest
アノテーション : 1,000 ms 程度で終わるようなテスト。 コンポーネント単体やいくつかのコンポーネントを結合してテストする場合に使用する。 ファイルアクセスや DB アクセス、コンテキストなどは使っていいけど、ネットワークアクセスなどのそこそこ時間がかかる非同期処理はテストに含めない。@LargeTest
アノテーション : アプリケーション全体のコンポーネントを統合してテストするようなもの。
これらはテストクラス自体に付けることもできますし、メソッド単体に付けることもできます。 実装を見たところ、メソッドとクラスの両方にアノテーションが付けられている場合はメソッドのアノテーションが優先されるようです。
ちなみに、Android Testing Support Library じゃなくて android.test.suitebuilder.annotation
パッケージの方にも同名のアノテーションがありますが、そっちは deprecated ぽいし AndroidJUnitRunner と組み合わせて使うことはできないぽいので注意しましょう。
AndroidJUnitRunner
とテストサイズによるフィルタリング
AndroidJUnitRunner
でテストを実行する場合、テストサイズによるフィルタリングが可能です。 下記 Javadoc にいろいろ書かれています。
adb
でテスト実行する場合
上のドキュメントでは、adb
コマンドでテストを実行する際にどういうオプションを渡せばいいかが主に書かれています。 例えば、small サイズのテストのみを実行する場合は、以下のようになります。
adb shell am instrument -w -e size small your.test.target/android.support.test.runner.AndroidJUnitRunner
Gradle の connectedAndroidTest
タスクで実行する場合
AndroidManifest.xml で指定する (ただし現在はバグで動かない)
上のドキュメントには All arguments can also be specified in the in the AndroidManifest via a meta-data tag
ということが書かれています。 すなわち、テスト用のアプリパッケージの AndroidManifest.xml ファイル (app/src/androidTest/AndroidManifest.xml ファイル) に以下のような記述をすると、small サイズのテストのみが実行されるはず、ということです。
<instrumentation android:name="android.support.test.runner.AndroidJUnitRunner" android:targetPackage="..."> <meta-data android:name="size" android:value="small"/> </instrumentation>
ただし現在はバグで動きません。 (指定が無視されます。) バグ報告を上げたので、対応状況は下記ページをご覧ください。
バグがなければ、上のような記述をしておけば ./gradlew :app:connectedAndroidTest
という感じで Gradle タスクでテストを実行したときにテストサイズのフィルタリングが効きます。
Gradle のビルドスクリプトで指定する
AndroidManifest.xml に書かずに Gradle のビルドスクリプトにオプションを指定することができます。 上の方法の代わりにこの方法を使うことで、上のバグを回避できます。 sumio さんに教えて頂きました。
@nobuoka もしコマンドラインからの実行で良いのであれば
— TOYAMA Sumio (@sumio_tym) May 26, 2016
build.gradle側で、
testInstrumentationRunnerArguments
を指定するので回避できたりしないでしょうか。こちらならManifestではなくargs扱いになるような気がします。
android { defaultConfig { testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" testInstrumentationRunnerArguments size: 'small' } }
上のような感じで書きます。
Android Studio 上でテストを実行する場合
Android Studio 上でテストを実行する場合は、build.gradle での記述が有効にならないので、configurations を弄る必要があります。 下図のような感じで、Extra options に 「-e size small」 と入力すれば良いです。
おわり
@SmallTest
アノテーションとか @LargeTest
アノテーションとかがあって、テスト実行時にそれらのフィルタリングができるという情報を過去に見たのですが、いざやってみるとあまり情報がなくてうまくいかなかったのでまとめてみました。
コミットごとのテストは @SmallTest
だけにして、ある程度開発が終わってレビューに出す前の段階になったら @MediumTest
と @LargeTest
のテストも行うようにする、とかにしたらテストにかかる時間が短くなっていいかもしれませんね。
関連ページ
- Androidオールスターズでテストの話をしました | RECRUIT TECHNOLOGIES Member's blog : テストサイズごとのテストのアプローチなどが書かれていて、思想的な部分も実際の実装の部分でも参考になります。
- GitHub - googlesamples/android-testing-templates : Google による Android Testing Support Library を使ったテスト記述のサンプルプロジェクト。 参考になります。
- Is there a way to only run a specific set of tests in an Android Gradle project? - Stack Overflow : sumio さんに教えてもらった後に気付きましたが、Stack Overflow でも同じ方法が紹介されていました。