Intents d'Espresso

Espresso-Intents est une extension d'Espresso, qui permet la validation et le bouchon des intents envoyés par l'application testée. Elle est semblable à Mockito, mais pour les intents Android.

Si votre application délègue des fonctionnalités à d'autres applications ou à la plate-forme, vous pouvez utiliser Espresso-Intents pour vous concentrer sur la logique de votre propre application, tout en supposant que les autres applications ou la plate-forme fonctionneront correctement. Avec Espresso-Intents, vous pouvez faire correspondre et valider vos intents sortants, ou même fournir des bouchons de réponses à la place des réponses d'intent réelles.

Inclure des Espresso-Intents dans votre projet

Dans le fichier app/build.gradle de votre application, ajoutez la ligne suivante dans dependencies:

Groovy

androidTestImplementation 'androidx.test.espresso:espresso-intents:3.4.0'

Kotlin

androidTestImplementation('androidx.test.espresso:espresso-intents:3.4.0')

Espresso-Intents n'est compatible qu'avec les bibliothèques de test Android 2.1 et 0.3 ou ultérieures. Veillez donc à mettre également à jour ces lignes:

Groovy

androidTestImplementation 'androidx.test:runner:1.4.0'
androidTestImplementation 'androidx.test:rules:1.4.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'

Kotlin

androidTestImplementation('androidx.test:runner:1.4.0')
androidTestImplementation('androidx.test:rules:1.4.0')
androidTestImplementation('androidx.test.espresso:espresso-core:3.4.0')

Écrire des règles de test

Avant d'écrire un test Espresso-Intents, configurez un IntentsTestRule. Il s'agit d'une extension de la classe ActivityTestRule qui facilite l'utilisation des API Espresso-Intents dans les tests d'interface utilisateur fonctionnels. Un IntentsTestRule initialise Espresso-Intents avant chaque test annoté avec @Test et libère Espresso-Intents après chaque exécution du test.

L'extrait de code suivant est un exemple de IntentsTestRule:

Kotlin

@get:Rule
val intentsTestRule = IntentsTestRule(MyActivity::class.java)

Java

@Rule
public IntentsTestRule<MyActivity> intentsTestRule =
    new IntentsTestRule<>(MyActivity.class);

Correspondance

Les intents Espresso permettent d'intercepter les intents sortants en fonction de certains critères de correspondance, définis à l'aide des outils de correspondance Hamcrest. Hamcrest vous permet de:

  • Utiliser un outil de mise en correspondance d'intent existant:option la plus simple, qui doit presque toujours être privilégiée.
  • Implémenter votre propre outil de mise en correspondance des intents:option la plus flexible. Pour en savoir plus, consultez la section intitulée "Écrire des outils de mise en correspondance personnalisés" du tutoriel Hamcrest.

Espresso-Intents propose les méthodes intended() et intending() pour la validation et le bouchon des intents, respectivement. Les deux utilisent un objet Hamcrest Matcher<Intent> comme argument.

L'extrait de code suivant montre une validation d'intent qui utilise des outils de mise en correspondance d'intents existants qui correspondent à un intent sortant qui lance un navigateur:

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");

Valider les intents

Espresso-Intents enregistre tous les intents qui tentent de lancer des activités à partir de l'application testée. À l'aide de la méthode intended(), qui est semblable à Mockito.verify(), vous pouvez confirmer qu'un intent donné a été vu. Cependant, Espresso-Intents ne bouchons pas les réponses aux intents, sauf si vous le configurez explicitement.

L'extrait de code suivant est un exemple de test qui valide un intent sortant qui lance une activité "téléphone" externe, mais ne bouchon pas les réponses:

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"));
}

Stubbing

À l'aide de la méthode intending(), qui est semblable à Mockito.when(), vous pouvez fournir une réponse bouchon pour les activités lancées avec startActivityForResult(). Cela est particulièrement utile pour les activités externes, car vous ne pouvez pas manipuler l'interface utilisateur d'une activité externe ni contrôler le ActivityResult renvoyé à l'activité testée.

Les extraits de code suivants implémentent un exemple de test activityResult_DisplaysContactsPhoneNumber(), qui vérifie que lorsqu'un utilisateur lance une activité de "contact" dans l'application testée, le numéro de téléphone du contact s'affiche:

  1. Compilez le résultat à renvoyer lorsqu'une activité particulière est lancée. L'exemple de test intercepte tous les intents envoyés aux "contacts" et bouchons leurs réponses avec un ActivityResult valide, à l'aide du code de résultat RESULT_OK.

    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);
    
  2. Demandez à Espresso de fournir l'objet de résultat du bouchon en réponse à toutes les invocations de l'intent "contacts" :

    Kotlin

    intending(toPackage("com.android.contacts")).respondWith(result)
    

    Java

    intending(toPackage("com.android.contacts")).respondWith(result);
    
  3. Vérifiez que l'action utilisée pour lancer l'activité produit le résultat bouchon attendu. Dans ce cas, l'exemple de test vérifie que le numéro de téléphone "123-345-6789" est renvoyé et s'affiche lors du lancement de l'activité "contacts" :

    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)));
    

Voici le test complet de 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)));
}

Ressources supplémentaires

Pour en savoir plus sur l'utilisation d'Espresso-Intents dans les tests Android, consultez les ressources suivantes.

Exemples