Espresso-Absichten

Espresso-Intents ist eine Erweiterung von Espresso, mit der Intents, die von der zu testenden Anwendung gesendet werden, validiert und gestubbt werden können. Es ist wie Mockito, aber für Android-Intents.

Wenn Ihre App Funktionen an andere Apps oder die Plattform delegiert, können Sie mit Espresso-Intents den Fokus auf die Logik Ihrer eigenen App legen und davon ausgehen, dass andere Apps oder die Plattform ordnungsgemäß funktionieren. Mit Espresso-Intents können Sie Ihre ausgehenden Intents abgleichen und validieren oder sogar Stub-Antworten anstelle von tatsächlichen Intent-Antworten bereitstellen.

Espresso-Intents in Ihr Projekt einbinden

Fügen Sie in der Datei app/build.gradle Ihrer App die folgende Zeile in dependencies ein:

Groovy

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

Kotlin

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

Espresso-Intents ist nur mit Espresso 2.1+ und Version 0.3+ der Android-Testbibliotheken kompatibel. Achten Sie also darauf, dass Sie auch diese Zeilen aktualisieren:

Groovy

androidTestImplementation 'androidx.test:runner:1.6.1'
androidTestImplementation 'androidx.test:rules:1.6.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.6.1'

Kotlin

androidTestImplementation('androidx.test:runner:1.6.1')
androidTestImplementation('androidx.test:rules:1.6.1')
androidTestImplementation('androidx.test.espresso:espresso-core:3.6.1')

Testregeln schreiben

Bevor Sie einen Espresso-Intents-Test schreiben, müssen Sie eine IntentsTestRule einrichten. Dies ist eine Erweiterung der Klasse ActivityTestRule, die die Verwendung von Espresso-Intents-APIs in funktionalen UI-Tests erleichtert. Ein IntentsTestRule initialisiert Espresso-Intents vor jedem Test, der mit @Test annotiert ist, und gibt Espresso-Intents nach jedem Testlauf frei.

Das folgende Code-Snippet ist ein Beispiel für ein IntentsTestRule:

Kotlin

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

Java

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

Übereinstimmung

Mit Espresso-Intents können ausgehende Intents anhand bestimmter Abgleichskriterien abgefangen werden, die mit Hamcrest Matchers definiert werden. Mit Hamcrest haben Sie folgende Möglichkeiten:

  • Vorhandenen Intent-Matcher verwenden:Dies ist die einfachste Option, die fast immer bevorzugt werden sollte.
  • Eigene Intent-Abgleichsfunktion implementieren:Die flexibelste Option. Weitere Informationen finden Sie im Abschnitt „Writing custom matchers“ im Hamcrest-Tutorial.

Espresso-Intents bietet die Methoden intended() und intending() für die Intent-Validierung bzw. das Stubbing. Beide verwenden ein Hamcrest-Matcher<Intent>-Objekt als Argument.

Das folgende Code-Snippet zeigt die Intent-Validierung mit vorhandenen Intent-Matcher, die einem ausgehenden Intent entsprechen, der einen Browser startet:

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

Intents validieren

Espresso-Intents zeichnet alle Intents auf, mit denen versucht wird, Aktivitäten aus der zu testenden Anwendung zu starten. Mit der Methode intended(), die Mockito.verify() ähnelt, können Sie bestätigen, dass eine bestimmte Intention erkannt wurde. Espresso Intents stubs jedoch keine Antworten auf Intents, es sei denn, Sie konfigurieren dies explizit.

Das folgende Code-Snippet ist ein Beispieltest, der Antworten auf einen ausgehenden Intent validiert, aber nicht stubs, der eine externe „phone“-Aktivität startet:

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

Mit der Methode intending(), die Mockito.when() ähnelt, können Sie eine Stub-Antwort für Aktivitäten bereitstellen, die mit startActivityForResult() gestartet werden. Das ist besonders bei externen Aktivitäten nützlich, da Sie die Benutzeroberfläche einer externen Aktivität nicht bearbeiten und die an die zu testende Aktivität zurückgegebenen ActivityResult nicht steuern können.

Die folgenden Code-Snippets implementieren einen Beispieltest für activityResult_DisplaysContactsPhoneNumber(), der prüft, ob die Telefonnummer des Kontakts angezeigt wird, wenn ein Nutzer in der zu testenden App eine „contact“-Aktivität startet:

  1. Erstellt das Ergebnis, das zurückgegeben werden soll, wenn eine bestimmte Aktivität gestartet wird. Im Beispieltest werden alle Intents abgefangen, die an „contacts“ gesendet werden, und ihre Antworten werden mit einem gültigen ActivityResult und dem Ergebniscode RESULT_OK simuliert.

    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. Weisen Sie Espresso an, das Stub-Ergebnisobjekt als Reaktion auf alle Aufrufe des Intents „contacts“ bereitzustellen:

    Kotlin

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

    Java

    intending(toPackage("com.android.contacts")).respondWith(result);
  3. Prüfen Sie, ob die Aktion, mit der die Aktivität gestartet wird, das erwartete Stub-Ergebnis liefert. In diesem Fall wird im Beispieltest geprüft, ob die Telefonnummer 123-345-6789 zurückgegeben und angezeigt wird, wenn die „Kontakte“-Aktivität gestartet wird:

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

Hier ist der vollständige activityResult_DisplaysContactsPhoneNumber()-Test:

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

Zusätzliche Ressourcen

Weitere Informationen zur Verwendung von Espresso-Intents in Android-Tests finden Sie in den folgenden Ressourcen.

Produktproben