UI-Tests automatisieren

Durch das Testen von Nutzerinteraktionen können Sie dafür sorgen, dass Nutzer keine unerwarteten Ergebnisse erhalten oder mit Ihrer App interagieren. Wenn Sie überprüfen müssen, ob die Benutzeroberfläche Ihrer App korrekt funktioniert, sollten Sie Tests für die Benutzeroberfläche erstellen.

Ein Ansatz für UI-Tests besteht darin, einen menschlichen Tester einfach eine Reihe von Nutzervorgängen in der Ziel-App durchführen zu lassen und zu überprüfen, ob sich diese korrekt verhält. Dieser manuelle Ansatz kann jedoch zeitaufwendig und fehleranfällig sein. Ein effizienterer Ansatz besteht darin, Ihre UI-Tests so zu schreiben, dass Nutzeraktionen automatisch ausgeführt werden. Mit dem automatisierten Ansatz können Sie Ihre Tests schnell und zuverlässig und wiederholbar ausführen.

UI-Tests starten eine App (oder einen Teil davon), simulieren dann Nutzerinteraktionen und prüfen schließlich, ob die App angemessen reagiert hat. Dies sind Integrationstests, die von der Verifizierung des Verhaltens einer kleinen Komponente bis hin zu einem großen Navigationstest, der einen gesamten User Flow durchlaufen, reichen können. Sie sind nützlich, um Regressionen zu prüfen und die Kompatibilität mit verschiedenen API-Levels und physischen Geräten zu prüfen.

Instrumentierte UI-Tests in Android Studio

Wenn Sie instrumentierte UI-Tests mit Android Studio ausführen möchten, implementieren Sie den Testcode in einem separaten Android-Testordner – src/androidTest/java. Das Android-Plug-in für Gradle erstellt eine Test-App basierend auf Ihrem Testcode und lädt die Test-App dann auf demselben Gerät wie die Ziel-App. In Ihrem Testcode können Sie UI-Test-Frameworks verwenden, um Nutzerinteraktionen in der Ziel-App zu simulieren und Testaufgaben auszuführen, die bestimmte Nutzungsszenarien abdecken.

Jetpack-Frameworks

Jetpack umfasst verschiedene Frameworks, die APIs zum Schreiben von UI-Tests bereitstellen:

  • Das Espresso-Test-Framework (Android 4.0.1, API-Level 14 oder höher) bietet APIs zum Schreiben von UI-Tests, um Nutzerinteraktionen mit Views innerhalb einer einzelnen Ziel-App zu simulieren. Ein Hauptvorteil von Espresso besteht darin, dass es eine automatische Synchronisierung von Testaktionen mit der Benutzeroberfläche der App bietet, die Sie testen. Espresso erkennt, wenn der Hauptthread inaktiv ist, und kann Ihre Testbefehle zum richtigen Zeitpunkt ausführen, wodurch die Zuverlässigkeit Ihrer Tests verbessert wird.
  • Jetpack Compose (Android 5.0, API-Level 21 oder höher) bietet eine Reihe von Test-APIs, um Compose-Bildschirme und -Komponenten zu starten und mit ihnen zu interagieren. Interaktionen mit Compose-Elementen werden mit Tests synchronisiert und haben die vollständige Kontrolle über Zeit, Animationen und Neuzusammensetzungen.
  • UI Automator (Android 4.3, API-Level 18 oder höher) ist ein Framework für UI-Tests, das sich für App-übergreifende Funktionstests in Systemen und installierten Apps eignet. Mit den UI Automator APIs können Sie Vorgänge wie das Öffnen des Menüs „Einstellungen“ oder des App Launchers auf einem Testgerät ausführen.
  • Mit Robolectric (Android 4.1, API-Level 16 oder höher) können Sie lokale Tests erstellen, die auf Ihrer Workstation oder Umgebung für kontinuierliche Integration in einer regulären JVM ausgeführt werden, anstatt auf einem Emulator oder Gerät. Es kann die Espresso- oder Compose-Test-APIs verwenden, um mit UI-Komponenten zu interagieren.

Schwäche und Synchronisierung

Der asynchrone Charakter mobiler Anwendungen und Frameworks erschwert häufig das Schreiben zuverlässiger und wiederholbarer Tests. Wenn ein Nutzerereignis injiziert wird, muss das Test-Framework warten, bis die App vollständig darauf reagiert. Dies kann von der Änderung eines Textes auf dem Bildschirm bis zur vollständigen Wiederherstellung einer Aktivität reichen. Wenn ein Test kein deterministisches Verhalten zeigt, ist er unzuverlässig.

Moderne Frameworks wie Compose oder Espresso sind auf das Testen ausgelegt, sodass es eine gewisse Garantie gibt, dass die UI vor der nächsten Testaktion oder Assertion inaktiv ist. Dies ist Synchronisierung.

Synchronisierung testen

Wenn Sie asynchrone oder Hintergrundvorgänge ausführen, die dem Test unbekannt sind, können Probleme auftreten, z. B. beim Laden von Daten aus einer Datenbank oder beim Anzeigen unendlicher Animationen.

Flussdiagramm mit einer Schleife, die vor dem Testlauf prüft, ob die App inaktiv ist
Abbildung 1: Synchronisierung testen

Um die Zuverlässigkeit Ihrer Testsuite zu erhöhen, können Sie eine Methode zur Nachverfolgung von Hintergrundvorgängen installieren, z. B. Espresso-Inaktivitätsressourcen. Außerdem können Sie Module für Testversionen ersetzen, die Sie auf Inaktivität abfragen oder die Synchronisierung verbessern können, z. B. TestDispatcher für Koroutinen oder RxIdler für RxJava.

Diagramm, das einen Testfehler zeigt, wenn die Synchronisierung auf dem Warten auf eine bestimmte Zeit basiert
Abbildung 2: Die Verwendung von Schlaf in Tests führt zu langsamen oder unzuverlässigen Tests.

Architektur und Testeinrichtung

Die Architektur Ihrer Anwendung sollte es Tests ermöglichen, Teile davon zum Testen von Double zu ersetzen, und Sie sollten Bibliotheken verwenden, die Dienstprogramme zur Unterstützung bei Tests bereitstellen. Sie können beispielsweise ein Daten-Repository-Modul durch eine speicherinterne Version davon ersetzen, die fiktive, deterministische Daten für den Test bereitstellt.

Produktions- und Testarchitekturdiagramme Produktionsdiagramm zeigt lokale und Remote-Datenquellen, die Daten an das Repository liefern, das diese wiederum asynchron an die Benutzeroberfläche übermittelt. Das Testdiagramm zeigt ein Fake-Repository, das seine Daten synchron mit der Benutzeroberfläche bereitstellt.
Abbildung 3: Testen einer UI durch Ersetzen der Abhängigkeiten durch Fälschungen.

Der empfohlene Ansatz zum Aktivieren dieser Funktion ist die Verwendung der Abhängigkeitsinjektion. Sie können Ihr eigenes System manuell erstellen. Wir empfehlen jedoch die Verwendung eines DI-Frameworks wie Hilt.

Warum automatische Tests?

Eine Android-App kann auf Tausende verschiedene Geräte über viele API-Level und Formfaktoren ausgerichtet sein. Aufgrund der umfangreichen Anpassungsmöglichkeiten des Betriebssystems kann die App falsch gerendert werden oder auf einigen Geräten sogar abstürzen.

Mit UI-Tests können Sie Kompatibilitätstests durchführen, um das Verhalten einer Anwendung in verschiedenen Kontexten zu prüfen. Sie können die UI-Tests auf Geräten ausführen, die sich auf folgende Arten unterscheiden:

  • API-Level: 21, 25 und 30
  • Sprache: Englisch, Arabisch und Chinesisch.
  • Ausrichtung: Hochformat, Querformat.

Außerdem sollten Apps nicht nur auf Smartphones, sondern auch auf das Verhalten überprüfen. Sie sollten Tablets, faltbare Smartphones und andere Geräte testen.

Weitere Informationen

Weitere Informationen zum Erstellen von UI-Tests finden Sie in den folgenden Ressourcen.

Dokumentation

Codelabs