In diesem Dokument wird erläutert, wie Sie häufige automatisierte Testaufgaben mithilfe der Espresso API
Die Espresso API regt Testautoren dazu an, darüber nachzudenken, was Nutzer
bei der Interaktion mit der Anwendung – UI-Elemente finden und interagieren
mit ihnen teilen. Gleichzeitig verhindert das Framework den direkten Zugriff auf Aktivitäten.
und Ansichten der Anwendung erstellen, da die Nutzung dieser Objekte
außerhalb des UI-Threads ist eine Hauptursache für instabile Tests. Daher werden Sie
Methoden wie getView()
und getCurrentActivity()
in der Espresso API nicht sehen.
Sie können weiterhin sicher mit Ansichten arbeiten, indem Sie eigene abgeleitete Klassen von
ViewAction
und ViewAssertion
.
API-Komponenten
Zu den Hauptkomponenten von Espresso gehören:
- Espresso – Einstiegspunkt für Interaktionen mit Aufrufen (über
onView()
undonData()
. Außerdem werden APIs zur Verfügung gestellt, die nicht unbedingt an eine Ansicht gebunden sind, wie alspressBack()
. - ViewMatchers – Eine Sammlung von Objekten, die die Klasse
Matcher<? super View>
-Schnittstelle. Sie können eine oder mehrereonView()
-Methode zum Suchen einer Ansicht in der aktuellen Ansichtshierarchie. - ViewActions: Eine Sammlung von
ViewAction
-Objekten, die an dieViewInteraction.perform()
-Methode, z. B.click()
. - ViewAssertions: Eine Sammlung von
ViewAssertion
-Objekten, die hat die MethodeViewInteraction.check()
übergeben. Meistens verwenden Sie stimmt mit Assertion überein. Dabei wird ein View-Matcher verwendet, um den Status des aktuell ausgewählte Ansicht.
Beispiel:
Kotlin
// withId(R.id.my_view) is a ViewMatcher // click() is a ViewAction // matches(isDisplayed()) is a ViewAssertion onView(withId(R.id.my_view)) .perform(click()) .check(matches(isDisplayed()))
Java
// withId(R.id.my_view) is a ViewMatcher // click() is a ViewAction // matches(isDisplayed()) is a ViewAssertion onView(withId(R.id.my_view)) .perform(click()) .check(matches(isDisplayed()));
Ansicht suchen
In den meisten Fällen wird für die onView()
-Methode ein Hamcrest-Matcher verwendet.
die nur mit genau einer Datenansicht in der aktuellen Ansicht übereinstimmen muss.
Hierarchie. Matcher sind leistungsstark und kennen diejenigen,
mit Mockito oder JUnit. Wenn Sie mit Hamcrest-Matchern nicht vertraut sind,
sollten Sie sich zunächst diese
Präsentation.
Häufig hat die gewünschte Ansicht eine eindeutige R.id
und einen einfachen withId
-Matcher
die Suche eingrenzen. Es gibt jedoch viele seriöse Fälle, in denen Sie
R.id
kann bei der Testentwicklungszeit nicht ermittelt werden. Zum Beispiel kann die spezifische Ansicht
hat möglicherweise kein R.id
oder das R.id
ist nicht eindeutig. Das kann sich normal
Instrumentierungstests anfällig und kompliziert zu schreiben, da der normale Weg
Zugriff auf die Ansicht – mit findViewById()
– funktioniert nicht. Daher können Sie
auf private Mitglieder der Aktivität oder des Fragments zugreifen müssen,
nach einem Container mit einem bekannten R.id
suchen und zum Inhalt für den
für eine bestimmte Ansicht.
Espresso bewältigt dieses Problem sauber, indem er Ihnen ermöglicht, die Ansicht einzugrenzen.
Sie können entweder vorhandene ViewMatcher
-Objekte oder eigene benutzerdefinierte Objekte verwenden.
Um eine Ansicht anhand ihrer R.id
zu finden, müssen Sie nur onView()
aufrufen:
Kotlin
onView(withId(R.id.my_view))
Java
onView(withId(R.id.my_view));
Manchmal werden R.id
-Werte von mehreren Datenansichten gemeinsam verwendet. In diesem Fall
Wenn Sie versuchen, ein bestimmtes R.id
-Objekt zu verwenden, erhalten Sie eine Ausnahme, z. B.
AmbiguousViewMatcherException
. In der Ausnahmemeldung wird eine Textnachricht
Darstellung der aktuellen Ansichtshierarchie, nach der Sie suchen und
die Ansichten, die mit dem nicht eindeutigen R.id
übereinstimmen:
java.lang.RuntimeException: androidx.test.espresso.AmbiguousViewMatcherException This matcher matches multiple views in the hierarchy: (withId: is <123456789>) ... +----->SomeView{id=123456789, res-name=plus_one_standard_ann_button, visibility=VISIBLE, width=523, height=48, has-focus=false, has-focusable=true, window-focus=true, is-focused=false, is-focusable=false, enabled=true, selected=false, is-layout-requested=false, text=, root-is-layout-requested=false, x=0.0, y=625.0, child-count=1} ****MATCHES**** | +------>OtherView{id=123456789, res-name=plus_one_standard_ann_button, visibility=VISIBLE, width=523, height=48, has-focus=false, has-focusable=true, window-focus=true, is-focused=false, is-focusable=true, enabled=true, selected=false, is-layout-requested=false, text=Hello!, root-is-layout-requested=false, x=0.0, y=0.0, child-count=1} ****MATCHES****
Wenn Sie die verschiedenen Attribute der Ansichten betrachten,
identifizierbaren Eigenschaften. Im obigen Beispiel enthält eine der Ansichten den Text
"Hello!"
Mit dieser Kombination können Sie Ihre Suche eingrenzen,
Matcher:
Kotlin
onView(allOf(withId(R.id.my_view), withText("Hello!")))
Java
onView(allOf(withId(R.id.my_view), withText("Hello!")));
Sie können auch festlegen, dass kein Abgleich rückgängig gemacht werden soll:
Kotlin
onView(allOf(withId(R.id.my_view), not(withText("Unwanted"))))
Java
onView(allOf(withId(R.id.my_view), not(withText("Unwanted"))));
Weitere Informationen finden Sie unter ViewMatchers
.
für die von Espresso bereitgestellten Tool zum Abgleich von Ansichten.
Wissenswertes
- Alle Ansichten, mit denen ein Nutzer interagieren kann, in einer gut funktionierenden App.
sollte entweder beschreibenden Text oder eine Inhaltsbeschreibung enthalten. Weitere Informationen finden Sie unter
Apps barrierefrei gestalten
Details. Wenn Sie die Suche nicht mit
withText()
eingrenzen können oderwithContentDescription()
, sollten Sie dies als Programmfehler in Bezug auf die Barrierefreiheit behandeln. - Den am wenigsten beschreibenden Matcher verwenden, mit dem die gesuchte Ansicht gefunden wird
für die Sie angegeben haben. Geben Sie nicht zu viele Details an, da das Framework dann zwingt, mehr Arbeit zu erledigen als
ist notwendig. Ist eine Ansicht beispielsweise anhand ihres Textes eindeutig identifizierbar, geben Sie
Sie müssen nicht angeben, dass die Ansicht auch über
TextView
zuweisbar ist. Viele Aufrufe, sollte dieR.id
des Aufrufs ausreichen. - Befindet sich die Zielansicht in einem
AdapterView
, z. B.ListView
,GridView
oderSpinner
: Die MethodeonView()
funktioniert möglicherweise nicht. In diesen Cases verwenden, sollten Sie stattdessenonData()
verwenden.
Aktion für eine Datenansicht ausführen
Wenn Sie einen passenden Abgleicher für die Zielansicht gefunden haben,
führen Sie mit der Perform-Methode Instanzen von ViewAction
dafür aus.
So klicken Sie beispielsweise auf die Ansicht:
Kotlin
onView(...).perform(click())
Java
onView(...).perform(click());
Mit einem „Perform Call“ können Sie mehrere Aktionen ausführen:
Kotlin
onView(...).perform(typeText("Hello"), click())
Java
onView(...).perform(typeText("Hello"), click());
Wenn sich die Ansicht, mit der Sie arbeiten, in einem ScrollView
(vertikal oder
horizontal), erwägen Sie die vorherigen Aktionen, für die die Ansicht
angezeigt werden, z. B. click()
und typeText()
, mit scrollTo()
. Dieses
stellt sicher, dass die Ansicht angezeigt wird, bevor mit der anderen Aktion fortgefahren wird:
Kotlin
onView(...).perform(scrollTo(), click())
Java
onView(...).perform(scrollTo(), click());
Weitere Informationen finden Sie unter ViewActions
.
für die Ansichtsaktionen von Espresso.
Assertions ansehen
Assertions können mit der check()
auf die aktuell ausgewählte Ansicht angewendet werden
. Die am häufigsten verwendete Assertion ist die Assertion matches()
. Dabei wird ein
ViewMatcher
-Objekt, um den Status der aktuell ausgewählten Ansicht zu bestätigen.
So prüfen Sie beispielsweise, ob eine Ansicht den Text "Hello!"
enthält:
Kotlin
onView(...).check(matches(withText("Hello!")))
Java
onView(...).check(matches(withText("Hello!")));
Wenn Sie bestätigen möchten, dass "Hello!"
Inhalt der Ansicht ist, gilt Folgendes als nicht empfehlenswert:
Kotlin
// Don't use assertions like withText inside onView. onView(allOf(withId(...), withText("Hello!"))).check(matches(isDisplayed()))
Java
// Don't use assertions like withText inside onView. onView(allOf(withId(...), withText("Hello!"))).check(matches(isDisplayed()));
Wenn Sie hingegen bestätigen möchten, dass eine Ansicht mit dem Text "Hello!"
z. B. nach einer Änderung der Kennzeichnung für die Sichtbarkeit von Aufrufen,
ist in Ordnung.
Einfacher Assertion-Test ansehen
In diesem Beispiel enthält SimpleActivity
einen Button
und einen TextView
. Wenn der Parameter
angeklickt wird, ändert sich der Inhalt von TextView
in "Hello Espresso!"
.
So testen Sie dies mit Espresso:
Klicken Sie auf die Schaltfläche.
Der erste Schritt besteht darin, nach einer Eigenschaft zu suchen, die dabei hilft, die Schaltfläche zu finden. Die
Schaltfläche im SimpleActivity
hat wie erwartet eine eindeutige R.id
.
Kotlin
onView(withId(R.id.button_simple))
Java
onView(withId(R.id.button_simple));
So führen Sie den Klick aus:
Kotlin
onView(withId(R.id.button_simple)).perform(click())
Java
onView(withId(R.id.button_simple)).perform(click());
TextView-Text überprüfen
Die TextView
mit dem zu bestätigenden Text hat auch eine eindeutige R.id
:
Kotlin
onView(withId(R.id.text_simple))
Java
onView(withId(R.id.text_simple));
So überprüfen Sie den Inhaltstext:
Kotlin
onView(withId(R.id.text_simple)).check(matches(withText("Hello Espresso!")))
Java
onView(withId(R.id.text_simple)).check(matches(withText("Hello Espresso!")));
Laden von Daten in Adapteransichten prüfen
AdapterView
ist eine spezielle Art von Widget, das Daten dynamisch aus
einen Adapter. Das häufigste Beispiel für ein AdapterView
ist ListView
. Als
statische Widgets wie LinearLayout
dagegen nur einen Teil der
AdapterView
untergeordnete Elemente können in die aktuelle Ansichtshierarchie geladen werden. Eine einfache
Bei der Suche mit onView()
wurden keine Ansichten gefunden, die momentan nicht geladen sind.
Espresso verarbeitet dies durch die Bereitstellung eines separaten onData()
-Einstiegspunkts,
das betreffende Adapterelement zuerst laden und vor der
oder einem seiner untergeordneten Elemente.
Warnung: Benutzerdefinierte Implementierungen von
AdapterView
kann Probleme mit onData()
haben
wenn sie Vererbungsverträge brechen,
getItem()
-API. In diesen Fällen ist es am besten,
Ihren Anwendungscode refaktorieren. Wenn dies nicht möglich ist, können Sie
Übereinstimmung mit dem benutzerdefinierten AdapterViewProtocol
. Weitere Informationen erhalten Sie in
seht euch die Standardeinstellungen an
<ph type="x-smartling-placeholder"></ph>
Die Klasse AdapterViewProtocols
wird von Espresso bereitgestellt.
Einfacher Test der Adapteransicht
Dieser einfache Test zeigt, wie onData()
verwendet wird. SimpleActivity
enthält einen
Spinner
mit einigen Elementen, die verschiedene Kaffeegetränke repräsentieren. Wenn ein
ausgewählt ist, gibt es einen TextView
, der sich in "One %s a day!"
ändert, wobei
%s
steht für das ausgewählte Element.
Das Ziel dieses Tests ist es, die Spinner
zu öffnen, ein bestimmtes Element auszuwählen und
Prüfen Sie, ob der TextView
das Element enthält. Da die Spinner
-Klasse auf
Am AdapterView
wird empfohlen, onData()
statt onView()
für
mit dem Artikel übereinstimmen.
Elementauswahl öffnen
Kotlin
onView(withId(R.id.spinner_simple)).perform(click())
Java
onView(withId(R.id.spinner_simple)).perform(click());
Element auswählen
Für die Elementauswahl erstellt Spinner
eine ListView
mit ihrem Inhalt.
Diese Ansicht kann sehr lang sein und das Element wird möglicherweise nicht zur Ansicht beigetragen
Hierarchie. Mit onData()
erzwingen wir das gewünschte Element in der Ansicht
Hierarchie. Die Elemente im Spinner
sind Strings, also möchten wir ein Element abgleichen.
der dem String "Americano"
entspricht:
Kotlin
onData(allOf(`is`(instanceOf(String::class.java)), `is`("Americano"))).perform(click())
Java
onData(allOf(is(instanceOf(String.class)), is("Americano"))).perform(click());
Überprüfe, ob der Text korrekt ist
Kotlin
onView(withId(R.id.spinnertext_simple)) .check(matches(withText(containsString("Americano"))))
Java
onView(withId(R.id.spinnertext_simple)) .check(matches(withText(containsString("Americano"))));
Fehlerbehebung
Espresso bietet nützliche Informationen zur Fehlerbehebung, wenn ein Test fehlschlägt:
Protokollierung
Espresso protokolliert alle Ansichtsaktionen an logcat. Beispiel:
ViewInteraction: Performing 'single click' action on view with text: Espresso
Hierarchie ansehen
Espresso druckt die Ansichtshierarchie in der Ausnahmemeldung aus, wenn onView()
schlägt fehl.
- Wenn
onView()
die Zielansicht nicht findet, wird einNoMatchingViewException
geworfen werden. Sie können die Ansichtshierarchie im Ausnahmestring überprüfen, um die Ansicht zu analysieren warum für den Matcher keine Übereinstimmung gefunden wurde. - Wenn
onView()
mehrere Ansichten findet, die mit dem angegebenen Matcher übereinstimmen, wird einAmbiguousViewMatcherException
wird geworfen. Die Ansichtshierarchie wird gedruckt und alle übereinstimmende Ansichten sind mit dem LabelMATCHES
gekennzeichnet:
java.lang.RuntimeException: androidx.test.espresso.AmbiguousViewMatcherException This matcher matches multiple views in the hierarchy: (withId: is <123456789>) ... +----->SomeView{id=123456789, res-name=plus_one_standard_ann_button, visibility=VISIBLE, width=523, height=48, has-focus=false, has-focusable=true, window-focus=true, is-focused=false, is-focusable=false, enabled=true, selected=false, is-layout-requested=false, text=, root-is-layout-requested=false, x=0.0, y=625.0, child-count=1} ****MATCHES**** | +------>OtherView{id=123456789, res-name=plus_one_standard_ann_button, visibility=VISIBLE, width=523, height=48, has-focus=false, has-focusable=true, window-focus=true, is-focused=false, is-focusable=true, enabled=true, selected=false, is-layout-requested=false, text=Hello!, root-is-layout-requested=false, x=0.0, y=0.0, child-count=1} ****MATCHES****
Bei einer komplizierten Ansichtshierarchie oder einem unerwarteten Verhalten von Widgets ist es immer hilfreich, die Funktion Hierarchy Viewer in Android Studio für eine Erklärung.
Warnungen bei der Adapteransicht
Espresso warnt Nutzer vor AdapterView
-Widgets. Wenn ein onView()
löst einen NoMatchingViewException
-Vorgang aus und AdapterView
-Widgets werden
in der Ansichtshierarchie ist die häufigste Lösung die Verwendung von onData()
.
Die Ausnahmemeldung enthält eine Warnung mit einer Liste der Adapteransichten.
Mit diesen Informationen können Sie onData()
aufrufen, um die Zielansicht zu laden.
Weitere Informationen
Weitere Informationen zur Verwendung von Espresso in Android-Tests finden Sie in der in den folgenden Ressourcen.
Produktproben
- CustomMatcherSample:
Erläutert das Erweitern von Espresso, damit er der Hinweiseigenschaft eines
EditText
-Objekts entspricht. - RecyclerViewSample:
RecyclerView
Aktionen für Espresso. - (Mehr...)