Espresso

Espresso-Web ist ein Einstiegspunkt für die Arbeit mit Android WebView-UI-Komponenten. Espresso-Web verwendet Atoms aus der beliebten WebDriver API, um das Verhalten einer WebView zu untersuchen und zu steuern.

Wann sollte Espresso-Web verwendet werden?

Mit Espresso-Web können Sie Hybrid-Apps testen, insbesondere die Integration der nativen UI-Komponenten Ihrer App mit den WebView-UI-Komponenten. Sie können die Espresso-Web API in Verbindung mit anderen Espresso APIs verwenden, um vollständig mit Webelementen in WebView-Objekten zu interagieren.

Wenn Sie nur die WebView und nicht die Interaktionen zwischen der WebView und nativen Komponenten in Ihrer App testen müssen, sollten Sie einen allgemeinen Webtest mit einem Framework wie WebDriver schreiben. Wenn Sie ein Webtest-Framework verwenden, benötigen Sie kein Android-Gerät oder keine Java-VM. Dadurch werden Ihre Tests schneller und zuverlässiger ausgeführt. Mit Espresso-Web können Sie Ihre benutzerdefinierten WebDriver-Atome wiederverwenden. Das bietet Ihnen viel Flexibilität, insbesondere wenn Sie Tests schreiben, die Sie sowohl für eigenständige Web-Apps als auch für Apps mit Android-Benutzeroberfläche ausführen möchten.

Funktionsweise

Ähnlich wie bei der onData()-Methode von Espresso besteht eine WebView-Interaktion aus mehreren Atoms. Für WebView-Interaktionen wird eine Kombination aus der Programmiersprache Java und einer JavaScript-Bridge verwendet. Da keine Race-Bedingungen durch die Bereitstellung von Daten aus der JavaScript-Umgebung entstehen können – alles, was Espresso auf der Java-basierten Seite sieht, ist eine isolierte Kopie – wird die Rückgabe von Daten aus Web.WebInteraction-Objekten vollständig unterstützt. So können Sie alle Daten überprüfen, die von einer Anfrage zurückgegeben werden.

Was ist ein WebDriver-Atom?

Das WebDriver-Framework verwendet Atoms, um Webelemente programmatisch zu finden und zu bearbeiten. Atoms werden von WebDriver verwendet, um die Browserbearbeitung zu ermöglichen. Ein Atom ist konzeptionell ähnlich wie eine ViewAction, eine in sich geschlossene Einheit, die eine Aktion in Ihrer Benutzeroberfläche ausführt. Sie machen Atoms über eine Liste definierter Methoden wie findElement() und getElement() verfügbar, um den Browser aus Nutzersicht zu steuern. Wenn Sie das WebDriver-Framework jedoch direkt verwenden, müssen Atoms richtig orchestriert werden, was eine sehr ausführliche Logik erfordert.

In Espresso kapseln die Klassen Web und Web.WebInteraction diesen Boilerplate-Code und ermöglichen eine Espresso-ähnliche Interaktion mit WebView-Objekten. Im Kontext von WebView werden Atoms als Ersatz für die traditionellen Espresso-Funktionen ViewMatchers und ViewActions verwendet.

Die API sieht dann ganz einfach aus:

Kotlin

onWebView()
    .withElement(Atom)
    .perform(Atom)
    .check(WebAssertion)

Java

onWebView()
    .withElement(Atom)
    .perform(Atom)
    .check(WebAssertion);

Weitere Informationen finden Sie in der Selenium-Dokumentation zu Atoms.

WebView implementieren

Folgen Sie der Anleitung in den folgenden Abschnitten, um WebView in den Tests Ihrer App zu verwenden.

Pakete

So binden Sie Espresso-Web in Ihr Projekt ein:

  1. Öffnen Sie die build.gradle-Datei Ihrer App. Dies ist in der Regel nicht die build.gradle-Datei der obersten Ebene, sondern app/build.gradle.
  2. Fügen Sie die folgende Zeile in „dependencies“ ein:

    Groovy

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

    Kotlin

        androidTestImplementation('androidx.test.espresso:espresso-web:3.6.1')
        
  3. Espresso-Web ist nur mit Espresso 2.2 oder höher und Version 0.3 oder höher der Testbibliothek 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')
        

Häufige API-Nutzung

Die Methode onWebView() ist der Haupteinstiegspunkt für die Arbeit mit WebView unter Android mit Espresso. Mit dieser Methode führen Sie Espresso-Webtests aus, z. B. die folgenden:

Kotlin

onWebView()
    .withElement(findElement(Locator.ID, "link_2")) // similar to onView(withId(...))
    .perform(webClick()) // Similar to perform(click())

    // Similar to check(matches(...))
    .check(webMatches(getCurrentUrl(), containsString("navigation_2.html")))

Java

onWebView()
    .withElement(findElement(Locator.ID, "link_2")) // similar to onView(withId(...))
    .perform(webClick()) // Similar to perform(click())

    // Similar to check(matches(...))
    .check(webMatches(getCurrentUrl(), containsString("navigation_2.html")));

In diesem Beispiel sucht Espresso-Web nach einem DOM-Element mit der ID "link_2" und klickt darauf. Das Tool prüft dann, ob die WebView eine GET-Anfrage mit dem String "navigation_2.html" sendet.

JavaScript-Unterstützung

Bei der Ausführung Ihrer Tests führt das System alle WebView-Interaktionen mit JavaScript aus. Damit JavaScript-Auswertungen unterstützt werden, muss JavaScript in der zu testenden WebView aktiviert sein.

Sie können erzwingen, dass JavaScript aktiviert wird, indem Sie forceJavascriptEnabled() als action in Ihrer zu testenden Aktivität aufrufen, wie im folgenden Code-Snippet gezeigt.

@RunWith(AndroidJUnit4::class)
class MyTestSuite {
    @get:Rule val activityScenarioRule =
        activityScenarioRule<MyWebViewActivity>()

    @Test fun testWebViewInteraction() {
        onWebView().forceJavascriptEnabled()
    }
}

Häufige Webinteraktionen

Häufige Interaktionen mit Web.WebInteraction-Objekten sind:

  • withElement() verweist auf ein DOM-Element innerhalb der WebView.

    Beispiel:

    Kotlin

    onWebView().withElement(findElement(Locator.ID, "teacher"))

    Java

    onWebView().withElement(findElement(Locator.ID, "teacher"));
  • withContextualElement() verweist auf ein DOM-Element mit Bereich innerhalb der WebView relativ zu einem anderen DOM-Element. Rufen Sie zuerst withElement() auf, um das Referenzobjekt Web.WebInteraction (DOM-Element) zu erstellen.

    Beispiel:

    Kotlin

    .withElement(findElement(Locator.ID, "teacher"))
        .withContextualElement(findElement(Locator.ID, "person_name"))

    Java

    .withElement(findElement(Locator.ID, "teacher"))
        .withContextualElement(findElement(Locator.ID, "person_name"));
  • check() wertet eine Bedingung aus und sorgt dafür, dass sie in true aufgelöst wird.

    Beispiel:

    Kotlin

    onWebView()
        .withElement(findElement(Locator.ID, "teacher"))
        .withContextualElement(findElement(Locator.ID, "person_name"))
        .check(webMatches(getText(), containsString("Socrates")))

    Java

    onWebView()
        .withElement(findElement(Locator.ID, "teacher"))
        .withContextualElement(findElement(Locator.ID, "person_name"))
        .check(webMatches(getText(), containsString("Socrates")));
  • perform() führt eine Aktion in einem WebView aus, z. B. das Klicken auf ein Element.

    Beispiel:

    Kotlin

    onWebView()
        .withElement(findElement(Locator.ID, "teacher"))
        .perform(webClick())

    Java

    onWebView()
        .withElement(findElement(Locator.ID, "teacher"))
        .perform(webClick());
  • reset() setzt die WebView auf ihren Ausgangszustand zurück. Das ist erforderlich, wenn durch eine vorherige Aktion, z. B. einen Klick, eine Navigationsänderung erfolgt, die den Zugriff auf ElementReference- und WindowReference-Objekte verhindert.

    Hinweis:Die Verwendung von reset() ist zwar nützlich, wenn Sie Zusicherungen für mehrseitige Arbeitsabläufe wie Formulareinsendungen erstellen, Ihre Tests sollten jedoch in der Regel auf eine einzelne Seite beschränkt sein.

    Beispiel:

    Kotlin

    onWebView()
        .withElement(...)
        .perform(...)
        .reset()

    Java

    onWebView()
        .withElement(...)
        .perform(...)
        .reset();

Beispiel

Im folgenden Beispiel wird getestet, ob nach der Eingabe von Text in eine WebView und der Auswahl einer Submit-Schaltfläche derselbe Text in einem anderen Element in derselben WebView angezeigt wird:

Kotlin

const val MACCHIATO = "Macchiato"

@RunWith(AndroidJUnit4::class)
class MyEspressoWebTestSuite {

    @Test fun typeTextInInput_clickButton_SubmitsForm() {
        // Create an intent that displays a web form.
        val webFormIntent = Intent()
        // ...

        // Lazily launch the Activity with a custom start Intent per test.
        ActivityScenario.launchActivity(webFormIntent)

        // Selects the WebView in your layout. If you have multiple WebView
        // objects, you can also use a matcher to select a given WebView,
        // onWebView(withId(R.id.web_view)).
        onWebView()
            // Find the input element by ID.
            .withElement(findElement(Locator.ID, "text_input"))

            // Clear previous input and enter new text into the input element.
            .perform(clearElement())
            .perform(DriverAtoms.webKeys(MACCHIATO))

            // Find the "Submit" button and simulate a click using JavaScript.
            .withElement(findElement(Locator.ID, "submitBtn"))
            .perform(webClick())

            // Find the response element by ID, and verify that it contains the
            // entered text.
            .withElement(findElement(Locator.ID, "response"))
            .check(webMatches(getText(), containsString(MACCHIATO)))
    }
}

Java

public static final String MACCHIATO = "Macchiato";

@Test
public void typeTextInInput_clickButton_SubmitsForm() {
    // Create an intent that displays a web form.
    Intent webFormIntent = new Intent();
    // ...

    // Lazily launch the Activity with a custom start Intent per test.
    ActivityScenario.launchActivity(webFormIntent);

    // Selects the WebView in your layout. If you have multiple WebView objects,
    // you can also use a matcher to select a given WebView,
    // onWebView(withId(R.id.web_view)).
    onWebView()
        // Find the input element by ID.
        .withElement(findElement(Locator.ID, "text_input"))

        // Clear previous input and enter new text into the input element.
        .perform(clearElement())
        .perform(DriverAtoms.webKeys(MACCHIATO))

        // Find the "Submit" button and simulate a click using JavaScript.
        .withElement(findElement(Locator.ID, "submitBtn"))
        .perform(webClick())

        // Find the response element by ID, and verify that it contains the
        // entered text.
        .withElement(findElement(Locator.ID, "response"))
        .check(webMatches(getText(), containsString(MACCHIATO)));
}

Zusätzliche Ressourcen

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

Produktproben

  • WebBasicSample: Verwenden Sie Espresso-Web, um mit WebView-Objekten zu interagieren.