Espresso-Intents は Espresso の拡張機能であり、テスト対象のアプリから送信されるインテントの検証とスタブ化をサポートします。Mockito に似ていますが、Android のインテントを対象とします。
テスト対象のアプリが他のアプリまたはプラットフォームに機能を委任している場合、Espresso-Intents を使用することにより、他のアプリまたはプラットフォームが正しく機能していると仮定して、対象アプリのロジックのテストに専念できます。Espresso-Intents を使用すれば、送信されるインテントのマッチングや検証を行えるうえ、実際のインテント レスポンスの代わりにスタブ レスポンスを使うこともできます。
プロジェクトへの Espresso-Intents の組み込み
アプリの app/build.gradle
ファイルで、dependencies
に次の行を追加します。
androidTestImplementation 'androidx.test.espresso:espresso-intents:3.1.0'
Espresso-Intents は、Espresso 2.1 以上および Android テスト ライブラリのバージョン 0.3 以上のみと互換性があるため、次の行も必ず更新してください。
androidTestImplementation 'androidx.test:runner:1.1.0'
androidTestImplementation 'androidx.test:rules:1.1.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0'
テストルールの作成
Espresso-Intents テストを作成する前に、IntentsTestRule
をセットアップします。これは ActivityTestRule
の拡張クラスであり、UI の機能テストで Espresso-Intents の API を簡単に使用できるようにします。IntentsTestRule
は、@Test
アノテーションが付けられた個々のテストの前に Espresso-Intents を初期化し、テストの実施後に Espresso-Intents を解放します。
次のコード スニペットは、IntentsTestRule
の例を示しています。
Kotlin
@get:Rule val intentsTestRule = IntentsTestRule(MyActivity::class.java)
Java
@Rule public IntentsTestRule<MyActivity> intentsTestRule = new IntentsTestRule<>(MyActivity.class);
マッチング
Espresso-Intents には、Hamcrest マッチャーで定義したマッチング基準に基づいて、送信されるインテントをインターセプトする機能が用意されています。Hamcrest により次のことが可能になります。
- 既存のインテント マッチャーの使用: 最も簡単なオプションであり、ほとんどの場合に推奨されます。
- 独自のインテント マッチャーの実装: 最も自由度の高いオプションです。詳細については、Hamcrest チュートリアルの「カスタム マッチャーの作成」セクションをご覧ください。
Espresso-Intents には、インテントの検証とスタブ化のために、それぞれ intended()
メソッドと intending()
メソッドが用意されています。どちらのメソッドも Hamcrest Matcher<Intent>
オブジェクトを引数として受け取ります。
次のコード スニペットは、既存のインテント マッチャーを使用したインテント検証の例を示しています。このマッチャーは、ブラウザを起動する発信インテントのマッチングを行います。
Kotlin
assertThat(intent).hasAction(Intent.ACTION_VIEW) assertThat(intent).categories().containsExactly(Intent.CATEGORY_BROWSABLE) assertThat(intent).hasData(Uri.parse("www.google.com")) assertThat(intent).extras().containsKey("key1") assertThat(intent).extras().string("key1").isEqualTo("value1") assertThat(intent).extras().containsKey("key2") assertThat(intent).extras().string("key2").isEqualTo("value2")
Java
assertThat(intent).hasAction(Intent.ACTION_VIEW); assertThat(intent).categories().containsExactly(Intent.CATEGORY_BROWSABLE); assertThat(intent).hasData(Uri.parse("www.google.com")); assertThat(intent).extras().containsKey("key1"); assertThat(intent).extras().string("key1").isEqualTo("value1"); assertThat(intent).extras().containsKey("key2"); assertThat(intent).extras().string("key2").isEqualTo("value2");
インテントの検証
Espresso-Intents は、テスト対象のアプリからアクティビティを起動しようとするすべてのインテントを記録します。Mockito.verify()
に似た intended()
メソッドを使用すると、特定のインテントが確認されたかどうかをアサーションできます。その一方で、Espresso-Intents は、明示的に構成しない限り、インテントへのレスポンスをスタブ化しません。
次のコード スニペットは、外部の「電話」アクティビティを起動する発信インテントについて、検証はするもののレスポンスのスタブ化は行わないテストの例です。
Kotlin
@Test fun validateIntentSentToPackage() { // User action that results in an external "phone" activity being launched. user.clickOnView(system.getView(R.id.callButton)) // Using a canned RecordedIntentMatcher to validate that an intent resolving // to the "phone" activity has been sent. intended(toPackage("com.android.phone")) }
Java
@Test public void validateIntentSentToPackage() { // User action that results in an external "phone" activity being launched. user.clickOnView(system.getView(R.id.callButton)); // Using a canned RecordedIntentMatcher to validate that an intent resolving // to the "phone" activity has been sent. intended(toPackage("com.android.phone")); }
スタブ化
Mockito.when()
に似た intending()
メソッドを使用すると、startActivityForResult()
で起動するアクティビティに対してスタブ レスポンスを提供できます。これは、外部アクティビティに対して特に有効です。外部アクティビティについては、そのユーザー インターフェースを操作したり、テスト対象のアクティビティに返される ActivityResult
を制御したりすることができないからです。
次のコード スニペットは、activityResult_DisplaysContactsPhoneNumber()
のサンプルテストを実装します。このテストでは、ユーザーがテスト対象アプリで「連絡先」アクティビティを起動したときに、連絡先の電話番号が表示されることを確認します。
特定のアクティビティが起動された際に返す結果を準備します。このサンプルテストでは、「連絡先」に送信されるすべてのインテントをインターセプトし、結果コード
RESULT_OK
を使用して、有効なActivityResult
を含むレスポンスをスタブ化します。Kotlin
val resultData = Intent() val phoneNumber = "123-345-6789" resultData.putExtra("phone", phoneNumber) val result = Instrumentation.ActivityResult(Activity.RESULT_OK, resultData)
Java
Intent resultData = new Intent(); String phoneNumber = "123-345-6789"; resultData.putExtra("phone", phoneNumber); ActivityResult result = new ActivityResult(Activity.RESULT_OK, resultData);
「連絡先」インテントの呼び出しすべてに対してスタブ結果オブジェクトを返すよう、Espresso に指示します。
Kotlin
intending(toPackage("com.android.contacts")).respondWith(result)
Java
intending(toPackage("com.android.contacts")).respondWith(result);
アクティビティの起動に使用するアクションによって期待するスタブ結果が生成されることを確認します。このサンプルテストでは、「連絡先アクティビティ」が起動されたときに、電話番号「123-345-6789」が返され、表示されることを確認しています。
Kotlin
onView(withId(R.id.pickButton)).perform(click()) onView(withId(R.id.phoneNumber)).check(matches(withText(phoneNumber)))
Java
onView(withId(R.id.pickButton)).perform(click()); onView(withId(R.id.phoneNumber)).check(matches(withText(phoneNumber)));
activityResult_DisplaysContactsPhoneNumber()
のテスト全体を次に示します。
Kotlin
@Test fun activityResult_DisplaysContactsPhoneNumber() { // Build the result to return when the activity is launched. val resultData = Intent() val phoneNumber = "123-345-6789" resultData.putExtra("phone", phoneNumber) val result = Instrumentation.ActivityResult(Activity.RESULT_OK, resultData) // Set up result stubbing when an intent sent to "contacts" is seen. intending(toPackage("com.android.contacts")).respondWith(result) // User action that results in "contacts" activity being launched. // Launching activity expects phoneNumber to be returned and displayed. onView(withId(R.id.pickButton)).perform(click()) // Assert that the data we set up above is shown. onView(withId(R.id.phoneNumber)).check(matches(withText(phoneNumber))) }
Java
@Test public void activityResult_DisplaysContactsPhoneNumber() { // Build the result to return when the activity is launched. Intent resultData = new Intent(); String phoneNumber = "123-345-6789"; resultData.putExtra("phone", phoneNumber); ActivityResult result = new ActivityResult(Activity.RESULT_OK, resultData); // Set up result stubbing when an intent sent to "contacts" is seen. intending(toPackage("com.android.contacts")).respondWith(result); // User action that results in "contacts" activity being launched. // Launching activity expects phoneNumber to be returned and displayed. onView(withId(R.id.pickButton)).perform(click()); // Assert that the data we set up above is shown. onView(withId(R.id.phoneNumber)).check(matches(withText(phoneNumber))); }
参考情報
Espresso-Intents を使用した Android のテストに関するその他の情報については、次のリソースをご覧ください。
サンプル
- IntentsBasicSample:
intended()
とintending()
の基本的な使用方法を示します。 - IntentsAdvancedSample: カメラを使用してビットマップを取得するユーザーの操作をシミュレートします。