Advertisement
  1. Code
  2. Android SDK

Testen von Android-Benutzeroberflächen mit Espresso

by
Difficulty:IntermediateLength:LongLanguages:

German (Deutsch) translation by Zhang Xiang Liang (you can also view the original English article)

In diesem Beitrag erfahren Sie, wie Sie UI-Tests mit dem Espresso-Testframework schreiben und Ihren Testworkflow automatisieren, anstatt den langwierigen und sehr fehleranfälligen manuellen Prozess zu verwenden.

Espresso ist ein Testframework zum Schreiben von UI-Tests in Android. Laut den offiziellen Dokumenten können Sie:

Verwenden Sie Espresso, um präzise, schöne und zuverlässige Android-UI-Tests zu schreiben.

1. Warum Espresso verwenden?

Eines der Probleme beim manuellen Testen besteht darin, dass die Durchführung zeitaufwändig und langwierig sein kann. Um beispielsweise einen Anmeldebildschirm (manuell) in einer Android-App zu testen, müssen Sie Folgendes tun:

  1. Starten Sie die App.
  2. Navigieren Sie zum Anmeldebildschirm.
  3. Bestätigen Sie, ob der BenutzernameTextBearbeiten und das PasswortTextBearbeiten sichtbar sind.
  4. Geben Sie den Benutzernamen und das Passwort in die entsprechenden Felder ein.
  5. Bestätigen Sie, ob die Anmeldeschaltfläche auch sichtbar ist, und klicken Sie dann auf diese Anmeldeschaltfläche.
  6. Überprüfen Sie, ob die richtigen Ansichten angezeigt werden, wenn diese Anmeldung erfolgreich war oder fehlgeschlagen ist.

Anstatt die ganze Zeit damit zu verbringen, unsere App manuell zu testen, ist es besser, mehr Zeit damit zu verbringen, Code zu schreiben, der unsere App von den anderen abhebt! Und obwohl manuelles Testen mühsam und ziemlich langsam ist, ist es dennoch fehleranfällig und Sie könnten einige Eckfälle verpassen.

Zu den Vorteilen des automatisierten Testens gehören:

  • Automatisierte Tests führen bei jeder Ausführung genau dieselben Testfälle aus.
  • Entwickler können ein Problem schnell erkennen, bevor es an das QA-Team gesendet wird.
  • Im Gegensatz zu manuellen Tests kann dies viel Zeit sparen. Durch Zeitersparnis können Softwareentwickler und das QA-Team stattdessen mehr Zeit für herausfordernde und lohnende Aufgaben aufwenden.
  • Es wird eine höhere Testabdeckung erreicht, was zu einer besseren Anwendungsqualität führt.

In diesem Tutorial lernen wir Espresso kennen, indem wir es in ein Android Studio-Projekt integrieren. Wir werden UI-Tests für einen Anmeldebildschirm und eine RecycleAnsicht schreiben und mehr über das Testen von Absichten erfahren.

Qualität ist keine Handlung, sondern eine Gewohnheit. - Pablo Picasso

2. Voraussetzungen

Um diesem Tutorial folgen zu können, benötigen Sie:

Ein Beispielprojekt (in Kotlin) für dieses Tutorial finden Sie in unserem GitHub-Repo, damit Sie es problemlos verfolgen können.

3. Erstellen Sie ein Android Studio Project

Starten Sie Ihr Android Studio 3 und erstellen Sie ein neues Projekt mit einer leeren Aktivität namens Hauptaktivität. Stellen Sie sicher, dass Einschließlich Kotlin Support aktiviert ist.

Create Android Project dialog

4. Richten Sie Espresso und AndroidJUnitRunner ein

Stellen Sie nach dem Erstellen eines neuen Projekts sicher, dass Sie die folgenden Abhängigkeiten aus der Android Testing Support Library in Ihrem build.gradle hinzufügen (obwohl Android Studio sie bereits für uns aufgenommen hat). In diesem Tutorial verwenden wir die neueste Version 3.0.2 der Espresso-Bibliothek (zum jetzigen Zeitpunkt).

Wir haben auch die Instrumentation Runner AndroidJUnitRunner aufgenommen:

Eine Instrumentation, die JUnit3- und JUnit4-Tests für ein Android-Paket (Anwendung) ausführt.

Beachten Sie, dass Instrumentation lediglich eine Basisklasse zum Implementieren von Anwendungsinstrumentierungscode ist.

Animation ausschalten

Wenn die Synchronisierung von Espresso, nicht weiß, wie auf das Ende einer Animation gewartet werden soll, kann das dazu führen, dass einige Tests fehlschlagen - wenn Sie die Animation auf Ihrem Testgerät zulassen. Um die Animation auf Ihrem Testgerät zu deaktivieren, gehen Sie zu Einstellungen > Entwickleroptionen und deaktivieren Sie alle folgenden Optionen im Abschnitt "Drawing":

  • Fensteranimationsskala
  • Übergangsanimationsskala
  • Animator-Dauer-Skala

5. Schreiben Sie Ihren ersten Test in Espresso

Zuerst testen wir einen Anmeldebildschirm. So beginnt der Anmeldefluss: Der Benutzer startet die App, und der erste angezeigte Bildschirm enthält eine einzelne Anmeldung. Wenn Sie auf dieses Einloggen klicken, wird der Bildschirm AnmeldungAktiv geöffnet. Dieser Bildschirm enthält nur zwei BearbeiteTexts (die Felder username und passwort) und eine Schaltfläche Versenden.

So sieht unser Hauptaktivität-Layout aus:

MainActivity layout

So sieht unser AnmeldeAktivität-Layout aus:

Schreiben wir jetzt einen Test für unsere HauptAktivität-Klasse. Gehen Sie zu Ihrer HauptAktivität-Klasse, bewegen Sie den Cursor auf den HauptAktivität-Namen und drücken Sie Shift-Control-T. Wählen Sie im Popup-Menü die Option Neuen Test erstellen.

Create new test dialog

Drücken Sie die OK-Taste und ein weiterer Dialog wird angezeigt. Wählen Sie das androidTest-Verzeichnis und klicken Sie erneut auf die Schaltfläche OK. Beachten Sie, dass sich die Testfälle im Ordner androidTest/java befinden, da wir einen Instrumentierungstest schreiben (Android SDK-spezifische Tests).

Jetzt hat Android Studio erfolgreich eine Testklasse für uns erstellt. Fügen Sie über dem Klassennamen die folgende Anmerkung ein: @RunWith(AndroidJUnit4::class).

Diese Anmerkung bedeutet, dass alle Tests in dieser Klasse Android-spezifische Tests sind.

Testaktivitäten

Da wir eine Aktivität testen möchten, müssen wir ein kleines Setup durchführen. Wir müssen Espresso darüber informieren, welche Aktivität vor dem Ausführen geöffnet oder gestartet werden soll, und nach dem Ausführen einer Testmethode zerstört werden soll.

Beachten Sie, dass die Annotation @Rule bedeutet, dass dies eine JUnit4-Testregel ist. JUnit4-Testregeln werden vor und nach jeder Testmethode ausgeführt (mit @Test versehen). In unserem eigenen Szenario möchten wir HauptAktivität vor jeder Testmethode starten und danach zerstören.

Wir haben auch die Kotlin Annotation @JvmField eingefügt. Dies weist den Compiler einfach an, keine getters und setters für die Eigenschaft zu generieren und sie stattdessen als einfaches Java-Feld verfügbar zu machen.

Hier sind die drei wichtigsten Schritte beim Schreiben eines Espresso-Tests:

  • Suchen Sie nach dem Widget (z. B. TextSehen oder Taste), das Sie testen möchten.
  • Führen Sie eine oder mehrere Aktionen für dieses Widget aus.
  • Vergleichen oder überprüfen Sie, ob sich das Widget jetzt in einem bestimmten Zustand befindet.

Die folgenden Arten von Anmerkungen können auf die in der Testklasse verwendeten Methoden angewendet werden.

  • @BeforeClass: Dies gibt an, dass die statische Methode, auf die diese Annotation angewendet wird, einmal und vor allen Tests in der Klasse ausgeführt werden muss. Dies kann beispielsweise verwendet werden, um eine Verbindung zu einer Datenbank herzustellen.
  • @Before: Gibt an, dass die Methode, an die diese Anmerkung angehängt ist, vor jeder Testmethode in der Klasse ausgeführt werden muss.
  • @Test: Gibt an, dass die Methode, an die diese Anmerkung angehängt ist, als Testfall ausgeführt werden soll.
  • @After: Gibt an, dass die Methode, an die diese Anmerkung angehängt ist, nach jeder Testmethode ausgeführt werden soll.
  • @AfterClass: Gibt an, dass die Methode, an die diese Anmerkung angehängt ist, ausgeführt werden soll, nachdem alle Testmethoden in der Klasse ausgeführt wurden. Hier schließen wir normalerweise Ressourcen, die in @BeforeClass geöffnet wurden.

Suchen einer View mit onView()

In unserer HauptAktivität-Layoutdatei haben wir nur ein Widget - die Schaltfläche Anmeldung. Testen wir ein Szenario, in dem ein Benutzer diese Schaltfläche findet, und klicken Sie darauf.

Um Widgets in Espresso zu finden, verwenden wir die statische Methode onView() (anstelle von findViewById()). Der Parametertyp, den wir für onView() bereitstellen, ist ein Matcher. Beachten Sie, dass die Matcher-API nicht aus dem Android SDK stammt, sondern aus dem Hamcrest-Projekt. Die Matcher-Bibliothek von Hamcrest befindet sich in der Espresso-Bibliothek, die wir über Gradle abgerufen haben.

Die onView(withId(R.id.btn_login)) gibt eine InteraktionAnzeigen zurück, die für eine Ansicht bestimmt ist, deren ID R.id.btn_login lautet. Im obigen Beispiel haben wir withId() verwendet, um nach einem Widget mit einer bestimmten ID zu suchen. Andere Ansichts-Matcher, die wir verwenden können, sind:

  • withText(): Gibt einen Matcher zurück, der TextView basierend auf seinem Texteigenschaftswert entspricht.
  • withHint(): Gibt einen Matcher zurück, der TextView basierend auf seinem Hinweis-Eigenschaftswert entspricht.
  • withTagKey(): Gibt einen Matcher zurück, der mit View basierend auf Tag-Schlüsseln übereinstimmt.
  • withTagValue(): Gibt einen Matcher zurück, der Views basierend auf Tag-Eigenschaftswerten entspricht.

Lassen Sie uns zunächst testen, ob die Schaltfläche tatsächlich auf dem Bildschirm angezeigt wird.

Hier bestätigen wir nur, ob die Schaltfläche mit der angegebenen ID (R.id.btn_login) für den Benutzer sichtbar ist, dazu verwenden wir die check() -Methode, um zu bestätigen, ob die zugrunde liegende Ansicht einen bestimmten Status hat - in unserem Fall wenn sie sichtbar ist.

Die statische Methode matches() gibt eine generische BehauptungAnzeigen zurück, die bestätigt, dass eine Ansicht in der Ansichtshierarchie vorhanden ist und vom angegebenen Ansichtsvergleicher abgeglichen wird. Dieser angegebene View Matcher wird durch Aufrufen von isDisplayed() zurückgegeben. Wie durch den Methodennamen vorgeschlagen, ist isDisplayed() ein Matcher, der Ansichten entspricht, die dem Benutzer derzeit auf dem Bildschirm angezeigt werden. Wenn wir beispielsweise überprüfen möchten, ob eine Schaltfläche aktiviert ist, übergeben wir einfach isEnabled() an matches().

Andere beliebte View-Matcher, die wir an die matches() -Methode übergeben können, sind:

  • hasFocus(): Gibt einen Matcher zurück, der Views entspricht, die derzeit den Fokus haben.
  • isChecked(): Gibt einen Matcher zurück, der genau dann akzeptiert, wenn die Ansicht ein CompoundButton (oder ein Subtyp von) ist und sich im aktivierten Zustand befindet. Das Gegenteil dieser Methode ist isNotChecked().
  • isSelected(): Gibt einen Matcher zurück, der den ausgewählten Views entspricht.

Um den Test auszuführen, können Sie auf das grüne Dreieck neben der Methode oder dem Klassennamen klicken. Durch Klicken auf das grüne Dreieck neben dem Klassennamen werden alle Testmethoden in dieser Klasse ausgeführt, während auf der Seite neben einer Methode der Test nur für diese Methode ausgeführt wird.

MainActivityTest class

Hurra! Unser Test ist bestanden!

Android Studio test result toolbar

Führen Sie Aktionen für eine Ansicht aus

In einem AnsichtInteraktion-Objekt, das durch Aufrufen von onView() zurückgegeben wird, können wir Aktionen simulieren, die ein Benutzer für ein Widget ausführen kann. Beispielsweise können wir eine Klickaktion simulieren, indem wir einfach die statische Methode click() in der AnsichtAktion-Klasse aufrufen. Dadurch wird ein AnsichtAktion-Objekt für uns zurückgegeben.

Die Dokumentation besagt, dass AnsichtAktion:

Verantwortlich für die Durchführung einer Interaktion mit dem angegebenen View-Element.

Wir führen ein Klickereignis durch, indem wir zuerst perform() aufrufen. Diese Methode führt die angegebenen Aktionen für die Ansicht aus, die vom aktuellen Ansichtsabgleich ausgewählt wurde. Beachten Sie, dass wir ihm eine einzelne Aktion oder eine Liste von Aktionen übergeben können (in der angegebenen Reihenfolge ausgeführt). Hier haben wir es click() gegeben. Andere mögliche Aktionen sind:

  • typeText() um die Eingabe von Text in einen EditText zu imitieren.
  • clearText() um das Löschen von Text in einem EditText zu simulieren.
  • doubleClick() um das Doppelklicken auf eine View zu simulieren.
  • longClick() um das lange Klicken auf eine View zu imitieren.
  • scrollTo() um das Scrollen einer ScrollView zu einer bestimmten View zu simulieren, die sichtbar ist.
  • swipeLeft() simuliert das Wischen von rechts nach links über die vertikale Mitte einer View.

In der ViewActions-Klasse finden Sie viele weitere Simulationen.

Mit View Assertions validieren

Lassen Sie uns unseren Test abschließen, um zu überprüfen, ob der Bildschirm AnmeldeAktion angezeigt wird, wenn auf die Schaltfläche Anmelden geklickt wird. Obwohl wir bereits gesehen haben, wie check() für eine AnsichtInteraktion verwendet wird, verwenden wir es erneut und übergeben ihm eine weitere BehauptungAnzeigen.

In der AnmeldeAktivität-Layoutdatei befindet sich neben TextBearbeiten und einer Taste auch ein TextAnsicht mit der ID R.id.tv_login. Wir überprüfen einfach, ob die TextAnsicht für den Benutzer sichtbar ist.

Jetzt können Sie den Test erneut ausführen!

Android Studio test result toolbar

Ihre Tests sollten erfolgreich bestanden werden, wenn Sie alle Schritte korrekt ausgeführt haben.

Folgendes ist während der Durchführung unserer Tests passiert:

  1. Startete die Hauptaktivität über das Feld Aktivitätsregel.
  2. Überprüft, ob die Anmelde-Schaltfläche (R.id.btn_login) für den Benutzer sichtbar war (isDisplayed()).
  3. Simulierte eine Klickaktion (click()) auf dieser Schaltfläche.
  4. Überprüft, ob die AnmeldeAktivität dem Benutzer angezeigt wurde, indem überprüft wird, ob eine TextAnsicht mit der ID R.id.tv_login in der AnmeldeAktivität sichtbar ist.

Sie können sich jederzeit auf den Espresso-Spickzettel beziehen, um die verschiedenen verfügbaren Ansichtsabgleiche, Ansichtsaktionen und Ansichtszusicherungen anzuzeigen.

6. Testen Sie den AnmeldeAktivität Bildschirm

Hier ist unsere LoginActivity.kt:

Wenn im obigen Code der eingegebene Benutzername "chike" und das Passwort "password" lautet, ist die Anmeldung erfolgreich. Bei jeder anderen Eingabe ist dies ein Fehler. Schreiben wir jetzt einen Espresso-Test dafür!

Gehen Sie zu LoginActivity.kt, bewegen Sie den Cursor auf den Namen AnmeldeAktivität und drücken Sie Shift-Control-T. Wählen Sie im Popup-Menü die Option Neuen Test erstellen.... Befolgen Sie den gleichen Vorgang wie für MainActivity.kt und klicken Sie auf die Schaltfläche OK.

Diese Testklasse ist unserer ersten sehr ähnlich. Wenn wir den Test ausführen, wird unser AnmeldeAktivität-Bildschirm geöffnet. Der Benutzername und das Passwort werden in die Felder R.id.et_username und R.id.et_password eingegeben. Als nächstes klickt Espresso auf die Schaltfläche Abschicken(R.id.btn_submit). Es wird gewartet, bis ein Ansicht mit der ID R.id.tv_login mit Text Erfolg gefunden werden kann.

7. Testen Sie eine Ansicht recyceln

Aktionen für die Recycler-Ansicht ist die Klasse, die eine Reihe von APIs für die Ausführung in RecyclerAnsicht verfügbar macht. Aktionen für die Recycler-Ansicht ist Teil eines separaten Artefakts innerhalb des espresso-contrib-Artefakts, das ebenfalls zu build.gradle hinzugefügt werden sollte:

Beachten Sie, dass dieses Artefakt auch die API zum Testen der Navigationsschublade über DrawerActions und DrawerMatchers enthält.

Um an einer beliebigen Stelle in einer RecyclerAnsicht auf ein Element zu klicken, rufen wir actionOnItemAtPosition() auf. Wir müssen ihm eine Art Gegenstand geben. In unserem Fall ist das Element der VersionsAnsicht-Klasse in unserem ZufallsAdapter die erste ist die Position und die zweite ist die Aktion (ViewActions.click()).

Andere Aktionen für die Recycler-Ansicht, die ausgeführt werden können, sind:

  • actionOnHolderItem(): Führt eine AnsichtAktion für eine Ansicht aus, die mit viewHolderMatcher übereinstimmt. Auf diese Weise können wir es anhand der im ViewHolder enthaltenen Elemente und nicht anhand der Position abgleichen.
  • scrollToPosition(): Gibt eine ViewAction zurück, mit der RecyclerView an eine Position gescrollt wird.

Als nächstes (sobald der Bildschirm "Notiz hinzufügen" geöffnet ist) geben wir unseren Notiztext ein und speichern die Notiz. Wir müssen nicht warten, bis der neue Bildschirm geöffnet wird - Espresso erledigt dies automatisch für uns. Es wartet, bis eine Ansicht mit der ID R.id.add_note_title gefunden wird.

8. Testabsichten

Espresso verwendet ein anderes Artefakt namens espresso-intents zum Testen von Intents. Dieses Artefakt ist nur eine weitere Erweiterung von Espresso, die sich auf die Validierung und Verspottung von Absichten konzentriert. Schauen wir uns ein Beispiel an.

Zuerst müssen wir die espresso-intents-Bibliothek in unser Projekt ziehen.

AbsichtTestregel erweitert AktivitätTestregel, sodass beide ein ähnliches Verhalten aufweisen. Folgendes sagt die Dokumentation:

Diese Klasse ist eine Erweiterung von AktivitätTestregel, die Espresso-Intents vor jedem mit Test kommentierten Test initialisiert und Espresso-Intents nach jedem Testlauf freigibt. Die Aktivität wird nach jedem Test beendet und diese Regel kann auf dieselbe Weise wie AktivitätTestregel verwendet werden.

Das Hauptunterscheidungsmerkmal besteht darin, dass es zusätzliche Funktionen zum Testen von startActivity() und startActivityForResult() mit Mocks und Stubs bietet.

Wir werden nun ein Szenario testen, in dem ein Benutzer auf eine Schaltfläche (R.id.btn_select_contact) auf dem Bildschirm klickt, um einen Kontakt aus der Kontaktliste des Telefons auszuwählen.

Hier verwenden wir intending() aus der espresso-intents-Bibliothek, um einen Stub mit einer Scheinantwort für unsere ACTION_PICK-Anfrage einzurichten. Folgendes passiert in PickContactActivity.kt, wenn der Benutzer auf die Schaltfläche mit der ID R.id.btn_select_contact klickt, um einen Kontakt auszuwählen.

intending() nimmt einen Matcher auf, der den Absichten entspricht, für die eine gestubbte Antwort bereitgestellt werden soll. Mit anderen Worten, der Matcher identifiziert, welche Anfrage Sie stubben möchten. In unserem Fall verwenden wir hasAction() (eine Hilfsmethode in IntentMatchers), um unsere ACTION_PICK-Anforderung zu finden. Wir rufen dann respondWith() auf, wodurch das Ergebnis für onActivityResult() festgelegt wird. In unserem Fall hat das Ergebnis Activity.RESULT_OK, das simuliert, wie der Benutzer einen Kontakt aus der Liste auswählt.

Wir simulieren dann das Klicken auf die Schaltfläche Kontakt auswählen, die startActivityForResult() aufruft. Beachten Sie, dass unser Stub die Scheinantwort an onActivityResult() gesendet hat.

Schließlich verwenden wir die Hilfsmethode intended(), um einfach zu überprüfen, ob die Aufrufe von startActivity() und startActivityForResult() mit den richtigen Informationen ausgeführt wurden.

Fazit

In diesem Tutorial haben Sie gelernt, wie Sie das Espresso-Testframework in Ihrem Android Studio-Projekt einfach verwenden können, um Ihren Testworkflow zu automatisieren.

Ich empfehle dringend, die offizielle Dokumentation zu lesen, um mehr über das Schreiben von UI-Tests mit Espresso zu erfahren.

Advertisement
Advertisement
Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.