Espresso-Absichten

Espresso-Intents ist eine Erweiterung von Espresso, die die Validierung und das Stubing von Intents ermöglicht, die von der zu testenden Anwendung gesendet werden. Es ist wie Mockito, aber für Android Intents.

Wenn Ihre App Funktionen an andere Apps oder die Plattform delegiert, können Sie Espresso-Intents verwenden, um sich auf die Logik Ihrer eigenen App zu konzentrieren und gleichzeitig davon auszugehen, 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:

Groovig

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

Kotlin

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

Espresso-Intents ist nur mit Espresso 2.1+ und Version 0.3+ der Android-Testbibliotheken kompatibel. Achte also darauf, diese Zeilen ebenfalls zu aktualisieren:

Groovig

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

Testregeln schreiben

Bevor Sie einen Espresso-Intents-Test schreiben, richten Sie ein IntentsTestRule ein. Dies ist eine Erweiterung der Klasse ActivityTestRule. Sie vereinfacht die Verwendung von Espresso-Intents APIs in funktionalen UI-Tests. Ein IntentsTestRule initialisiert Espresso-Intents vor jedem Test, der mit @Test annotiert ist, und gibt nach jedem Testlauf Espresso-Intents 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

Espresso-Intents bietet die Möglichkeit, ausgehende Intents anhand bestimmter Abgleichskriterien abzufangen, die mit Hamcrest-Matchern definiert werden. Hamcrest bietet Ihnen folgende Möglichkeiten:

  • Vorhandenen Intent-Matcher verwenden:Dies ist die einfachste Option, die fast immer bevorzugt werden sollte.
  • Eigenen Intent-Matcher implementieren: Die flexibelste Option. Weitere Informationen finden Sie in der Hamcrest-Anleitung im Abschnitt „Benutzerdefinierte Matcher schreiben“.

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

Das folgende Code-Snippet zeigt die Intent-Validierung, bei der vorhandene Intent-Matcher verwendet werden, die mit einem ausgehenden Intent übereinstimmen, 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, die versuchen, Aktivitäten aus der zu testenden Anwendung zu starten. Mit der Methode intended(), die mit Mockito.verify() vergleichbar ist, können Sie bestätigen, dass ein bestimmter Intent erkannt wurde. Espresso-Intents blockiert Antworten auf Intents jedoch nur, wenn Sie dies explizit konfigurieren.

Das folgende Code-Snippet ist ein Beispieltest, mit dem Antworten auf einen ausgehenden Intent geprüft, aber nicht blockiert werden, wenn er eine externe Telefonaktivitä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 der Methode Mockito.when() ähnelt, können Sie eine Stub-Antwort für Aktivitäten bereitstellen, die mit startActivityForResult() gestartet werden. Dies ist besonders bei externen Aktivitäten nützlich, da Sie weder die Benutzeroberfläche einer externen Aktivität bearbeiten noch das ActivityResult steuern können, das an die zu testende Aktivität zurückgegeben wird.

Mit den folgenden Code-Snippets wird ein activityResult_DisplaysContactsPhoneNumber()-Beispieltest implementiert, der bestätigt, dass die Kontakttelefonnummer angezeigt wird, wenn ein Nutzer in der zu testenden App eine „Kontakt“-Aktivität startet:

  1. Erstellen Sie das Ergebnis, das zurückgegeben wird, wenn eine bestimmte Aktivität gestartet wird. Der Beispieltest fängt alle Intents ab, die an „Kontakte“ gesendet werden, und beendet ihre Antworten mit einem gültigen ActivityResult unter Verwendung des Ergebniscodes 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. Weisen Sie Espresso an, das Stub-Ergebnisobjekt als Antwort 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 zum Starten der Aktivität verwendete Aktion das erwartete Stub-Ergebnis liefert. In diesem Fall wird im Beispieltest geprüft, ob die Telefonnummer "123-345-6789" zurückgegeben und beim Start der Kontaktaktivität angezeigt 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)));
}

Weitere Informationen

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

Produktproben