UI Automator ist ein Framework von Google für automatisiertes UI-Testing von Android-Anwendungen, das auf Systemebene arbeitet und mit Schnittstellenelementen über eine einzelne App hinaus interagieren kann. Im Gegensatz zu Espresso ist UI Automator nicht an den Prozess einer bestimmten App gebunden: Es kann Systemdialoge, die Benachrichtigungsleiste öffnen und zwischen Apps wechseln. Laut Google Android Developers verwendet UI Automator den standardmäßigen Accessibility Service, um auf den UI-Baum des Geräts zuzugreifen.
Wichtigste Erkenntnisse
UI Automator ist ein Framework für funktionale UI-Tests von Android, das auf Betriebssystemebene arbeitet. Es bietet eine API für den Zugriff auf jedes Element auf dem Gerätebildschirm, unabhängig davon, zu welcher App es gehört — einschließlich der Systemstatusleiste, Berechtigungsdialoge, des Startbildschirms und von Drittanbieter-Apps. Dies macht es unverzichtbar für das Testen von Szenarien, die über eine einzelne App hinausgehen.
Architektonisch verwendet UI Automator den Accessibility Service — denselben Dienst, der von TalkBack, Switch Access und anderen Barrierefreiheitstools verwendet wird. Über diesen Dienst erhält das Framework den vollständigen UI-Komponentenbaum des aktuellen Bildschirms und ermöglicht Aktionen auf diesen: Tippen, Wischen, Texteingabe und langes Drücken.
UI Automator erschien erstmals in Android 4.3 (API 18) und ist seitdem als offizielles Tool von Google für Cross-Application-Tests Teil der Android Testing Support Library. In AndroidX Test ist es als separates Artefakt androidx.test.uiautomator:uiautomator Version 2.3.0 (2024) verfügbar, das alle Android-Versionen ab API 18 unterstützt.
Funktionsprinzip: UI Automator basiert auf dem Scannen des Accessibility-Baums des aktuellen Bildschirms. Wenn die Methode findObject(selector) aufgerufen wird, durchläuft das Framework die View-Hierarchie, findet das erste Element, das den UiSelector-Bedingungen entspricht, und gibt ein UiObject zurück — einen Proxy für die Interaktion mit der tatsächlichen View.
Ein typischer UI Automator-Test beginnt mit dem Erhalt einer UiDevice-Instanz, die das physische Gerät repräsentiert. UiDevice bietet Methoden zum Auffinden von Elementen, Verwalten von Tastendrücken (Home, Zurück, Recent), Drehen des Bildschirms und Erstellen von Screenshots. Nachdem ein Element über UiSelector gefunden wurde, werden Aktionen auf dem UiObject ausgeführt.
Im folgenden Beispiel öffnet der Test die Einstellungen-App, findet das Element „Akku“ anhand des Textes und tippt darauf. UI Automator erfordert kein Starten einer Activity — es funktioniert mit jedem Bildschirm auf dem Gerät, einschließlich Drittanbieter-Apps.
val device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
// Einstellungsbildschirm öffnen
device.pressHome()
device.wait(Until.hasObject(UiSelector().text("Einstellungen")), 2000)
// Element "Akku" finden und tippen
val batteryItem = device.findObject(
UiSelector().text("Akku")
)
batteryItem.clickAndWait(Until.newWindow(), 3000)
UiDevice ist die Hauptklasse für die Interaktion mit dem Gerät. Es bietet Methoden zum Auffinden von Elementen, Simulieren von Hardwaretastendrücken (Home, Zurück, Menü, Lautstärke), Verwalten der Stromversorgung, Erstellen von Screenshots und Warten auf bestimmte Bildschirmzustände. UiDevice wird einmal pro Test erstellt und für alle Operationen wiederverwendet.
UiSelector ist eine fließende API zum Auffinden von UI-Elementen. Anders als Espresso ViewMatchers benötigt UiSelector keine Kompilierung — Suchbedingungen werden durch eine Methodenkette gebildet: text(), className(), description(), resourceId(), index(). Mehrere Bedingungen werden automatisch über logisches UND kombiniert.
| UiSelector-Methode | Zweck |
|---|---|
| text(String) | Suche nach exaktem Elementtext |
| textContains(String) | Suche nach teilweiser Textübereinstimmung |
| resourceId(String) | Suche nach Ressourcen-ID (z.B. com.example:id/button) |
| className(String) | Suche nach View-Klassennamen |
| description(String) | Suche nach content-description |
| childSelector(selector) | Suche nach einem Kindelement in einem Container |
Wenn sich mehrere Elemente auf dem Bildschirm denselben Text teilen, erlaubt UiSelector die Kombination von Kriterien: Finden Sie einen Container anhand der ID, dann darin — ein Element anhand von Text und Klasse. Dies garantiert eine eindeutige Identifizierung der gewünschten Komponente. Die Methode childSelector schränkt den Suchbereich auf einen bestimmten Container ein und beschleunigt die Navigation im UI-Baum.
val scrollView = device.findObject(
UiSelector().resourceId("android:id/list")
)
// Innerhalb der Liste das Element mit Text "Wi-Fi" finden
val wifiItem = scrollView.findObject(
UiSelector().text("Wi-Fi")
wifiItem.click()
Cross-Application (anwendungsübergreifende) Tests sind die Hauptfunktion, für die UI Automator gewählt wird. Das Framework kann zwischen Apps wechseln, OAuth-Login über einen Browser testen, Systemdialoge (Berechtigungen, App-Auswahl) überprüfen und mit der Systemstatusleiste, dem Benachrichtigungsfeld und dem Sperrbildschirm interagieren.
Ein typisches Cross-App-Testszenario: Die App öffnet einen Browser für die OAuth-Autorisierung, der Benutzer gibt seinen Benutzernamen und sein Passwort ein, und der Browser leitet zurück zur App. UI Automator wechselt zwischen Prozessen, findet Eingabefelder im Browser, füllt sie aus und tippt auf „Anmelden“.
// Warten auf das Erscheinen des Browsers
device.wait(Until.hasObject(
UiSelector().packageName("com.android.chrome")
), 5000)
// Suche nach E-Mail-Eingabefeld im Browser
val emailField = device.findObject(
UiSelector().className("android.widget.EditText").instance(0)
)
emailField.text = "user@example.com"
UI Automator kann Systemdialoge überprüfen und schließen — Standortberechtigungen, Benachrichtigungen, Dateizugriff. Dies ist kritisch wichtig für das Testen von Erstimstartszenarien, wenn das System nacheinander mehrere Berechtigungen anfordert. Ohne UI Automator können solche Szenarien nicht automatisiert werden, da Systemdialoge nicht zum Prozess der App gehören.
Die Wahl zwischen UI Automator und Espresso hängt vom Testszenario ab. Espresso ist optimiert für das Testen einer einzelnen App mit automatischer Synchronisierung und minimalem Boilerplate. UI Automator eignet sich für Szenarien, in denen mit dem System, dem Browser oder mehreren Apps interagiert werden muss.
| Kriterium | UI Automator | Espresso |
|---|---|---|
| Umfang | Gesamtes Gerät, mehrere Apps | Einzelne App |
| Synchronisierung | Manuell (warten, schlafen) | Automatisch (Idling Resource) |
| Geschwindigkeit | Langsamer (Zugriff über Dienst) | Schneller (arbeitet innerhalb des Prozesses) |
| System-UI | Unterstützt (Benachrichtigungen, Schnelleinstellungen) | Nicht unterstützt |
| Suchgenauigkeit | UiSelector nach Attributen | ViewMatchers nach Typ und Hierarchie |
| Stabilität | Niedriger (abhängig von Zeitvorgaben) | Höher (automatisches Warten) |
In der Praxis werden diese Frameworks oft zusammen verwendet: Espresso deckt UI-Tests der Haupt-App mit hoher Stabilität ab, während UI Automator für Szenarien eingesetzt wird, die über die App-Grenzen hinausgehen — OAuth-Login, Systemberechtigungen, Arbeiten mit Share Intent. Diese Kombination bietet maximale UI-Abdeckung bei minimalen Testwartungskosten.
Die Integration von UI Automator erfolgt durch Hinzufügen einer Abhängigkeit in build.gradle. Das Framework ist Teil von AndroidX Test und erfordert keine zusätzlichen Berechtigungen im Manifest — der Zugriff auf den Accessibility Service wird automatisch konfiguriert, wenn der instrumentierte Test gestartet wird.
Die minimale Konfiguration umfasst das Artefakt uiautomator und den standardmäßigen AndroidJUnitRunner-Testrunner. UI Automator-Tests werden im Verzeichnis src/androidTest abgelegt und auf einem Emulator oder physischen Gerät mit Android API 18+ ausgeführt.
dependencies {
androidTestImplementation("androidx.test.uiautomator:uiautomator:2.3.0")
androidTestImplementation("androidx.test.ext:junit:1.2.1")
androidTestImplementation("androidx.test:runner:1.6.1")
}
Zum Erhalt einer UiDevice-Instanz wird InstrumentationRegistry.getInstrumentation() verwendet. UiDevice sollte einmal in der setUp()-Methode erstellt und über alle Tests der Klasse hinweg wiederverwendet werden, um Geräteressourcen zu schonen. Es ist wichtig zu beachten, dass UiDevice nicht threadsicher ist — alle Operationen müssen im selben Thread der Testmethode ausgeführt werden. Das Erstellen eines neuen UiDevice in jedem Test verursacht Overhead und verlangsamt die Ausführung. Es wird empfohlen, UiDevice einmal in der beforeClass-Methode zu erstellen und für alle Tests der Testklasse wiederzuverwenden.
Anders als Espresso hat UI Automator keine automatische Synchronisierung. Zum Warten auf das Erscheinen von Elementen wird die Methode UiDevice.wait(condition, timeout) mit einem Until-Objekt verwendet: Until.findObject(selector), Until.hasObject(selector), Until.gone(selector). Ohne korrekte Wartezeiten werden Tests aufgrund von Race Conditions instabil — ein Element könnte zum Zeitpunkt der Suche noch nicht auf dem Bildschirm erschienen sein. Es wird empfohlen, ein Zeitlimit von mindestens 3–5 Sekunden für die Stabilität einzustellen.
Häufig gestellte Fragen
UI Automator arbeitet auf der Ebene des Accessibility Service und kann mit jeder App interagieren. Espresso arbeitet innerhalb des Prozesses einer einzelnen App und verwendet automatische Synchronisierung mit dem UI-Thread. UI Automator ist besser für anwendungsübergreifende Szenarien, während Espresso besser für stabile Einzel-App-Tests ist.
Ja, UI Automator funktioniert auf allen Geräten mit Android API 18+. Es benötigt keinen Root-Zugriff — es verwendet den standardmäßigen Accessibility Service, der über Instrumentation beim Starten der Tests aktiviert wird.
UI Automator verwendet den Accessibility Service, um den vollständigen UI-Komponentenbaum des aktuellen Bildschirms zu erhalten. Dann durchläuft UiSelector diesen Baum und findet Elemente anhand der angegebenen Kriterien: Text, Klasse, ID, content-description oder einer Kombination davon.
Ja, die Methode UiDevice.takeScreenshot(storePath) ermöglicht es, einen Screenshot des aktuellen Bildschirms zu erstellen und in einer Datei zu speichern. Dies ist nützlich für die Fehlersuche: Wenn ein Test fehlschlägt, kann der Screenshot gespeichert und der Bildschirmzustand analysiert werden.
UI Automator hat keine automatische Synchronisierung, daher sind Tests zeitabhängig. Wenn eine Animation nicht abgeschlossen ist oder eine View noch nicht gerendert wurde, kann findObject das Element möglicherweise nicht finden. Die Lösung ist die Verwendung von UiDevice.wait() mit einem ausreichenden Timeout.
Zusammenfassung
Das UI Automator-Toolset deckt alle wichtigen Cross-Application-Testszenarien ab und ist der Standard für Android-Automatisierung auf Systemebene.
Wir entwickeln eine mobile Applikation schlüsselfertig
IT Sectr entwickelt seit 2017 iOS- und Android-Apps für Startups und Unternehmen. Wir beraten Sie und schlagen die beste Lösung vor.
Lesen Sie auch