Mobile App-Automatisierung auf echten Geräten
Baue zuverlässige mobile App-Automatisierung auf echten Geräten mit Appium, ADB, UIAutomator und XCUITest auf, inklusive Lösungen für Flakiness, Parallelisierung über die Flotte und CI-Integration.
Mobile App-Automatisierung auf echten Geräten nutzt Frameworks wie Appium, ADB, UIAutomator und XCUITest, um physische Smartphones durch wiederholbare Abläufe zu steuern. Der Betrieb auf echter Hardware – und die Parallelisierung über eine Flotte – liefert eine Regressionsabdeckung und ein Performance-Signal, das Emulatoren nicht erreichen.
- The core stacks are Appium (cross-platform), UIAutomator/Espresso and ADB (Android), and XCUITest (iOS); scrcpy is invaluable for observing and debugging Android runs.
- Prefer written, versioned scripts over record-and-playback for anything you will maintain; recording is fine for one-off exploration.
- Flakiness is the main enemy — solve it with explicit waits and stable selectors, not sleeps.
- A fleet's value is parallelization: shard suites across devices to keep wall-clock time low.
- Wire automation into CI so every build runs against a real-device core tier.
Der Automatisierungs-Stack
Appium
Appium ist die verbreitetste plattformübergreifende Wahl. Es stellt das W3C-WebDriver-Protokoll bereit, sodass du Tests in der Sprache deiner Wahl schreibst und Android und iOS über eine einzige API steuerst. Im Hintergrund delegiert Appium an plattformspezifische Automatisierungs-Engines – UIAutomator2/Espresso auf Android, XCUITest auf iOS –, sodass du native Steuerung mit einer portablen Schnittstelle erhältst. Es eignet sich für Teams, die ein Framework und eine Test-Codebasis über Plattformen hinweg wollen.
ADB (Android Debug Bridge)
ADB ist das Schweizer Taschenmesser für Android. Über das Installieren und Starten von Apps hinaus steuert es Aktionen auf Shell-Ebene: Berechtigungen erteilen, Netzwerk und Sprache einstellen, Eingabeereignisse simulieren, Logcat erfassen, Screenshots abrufen, den Flugmodus umschalten und Bedingungen für Tests herstellen. Der Großteil der Android-Automatisierung stützt sich auf ADB für Setup, Teardown und die Kontrolle des Gerätezustands, selbst wenn die UI-Steuerung über ein anderes Framework läuft.
UIAutomator und Espresso
Für reine Android-Teams deckt Espresso (in-process, White-Box, schnell und stabil) die UI der eigenen App ab, während UIAutomator app-übergreifende Interaktionen und die System-UI übernimmt (Benachrichtigungen, Berechtigungsdialoge, Einstellungen). Sie werden oft zusammen eingesetzt.
XCUITest
XCUITest ist Apples natives UI-Framework, das über Xcode läuft. Es ist der zuverlässigste Weg für iOS-UI-Automatisierung und das, was Appium unter der Oberfläche auf iOS steuert. Für plattformspezifisches Verhalten und Unterschiede im Setup siehe iOS vs. Android-Flotten.
scrcpy
scrcpy spiegelt und steuert ein Android-Gerät über USB oder TCP/IP mit geringer Latenz. Es ist kein Test-Framework, aber der schnellste Weg, einen automatisierten Lauf zu beobachten, einen Fehler interaktiv zu reproduzieren und Selektoren live zu debuggen.
| Appium (cross-platform) | Native (Espresso / XCUITest) | |
|---|---|---|
| Codebase | One test suite, both platforms | Separate suite per platform |
| Speed & stability | Good, one layer of indirection | Fastest, most stable on its platform |
| System UI access | Via UIAutomator delegation | Direct (UIAutomator/XCUITest) |
| Best fit | Small team, shared flows | Platform-specific team, max reliability |
Skript versus Aufzeichnung
Record-and-Playback-Tools erzeugen ein Skript, indem sie deine Tipps aufzeichnen. Sie sind für einen ersten Entwurf oder eine Wegwerf-Prüfung attraktiv, aber aufgezeichnete Skripte neigen dazu, brüchig zu sein: Sie kodieren Koordinaten oder instabile Selektoren fest und haben nicht die Struktur, um im großen Maßstab gepflegt zu werden.
Handgeschriebene Skripte gewinnen bei allem, was Bestand haben soll. Sie erlauben stabile Lokatoren (Accessibility-IDs, Ressourcen-IDs), das Auslagern wiederverwendbarer Schritte, das Parametrisieren von Daten, das Hinzufügen von Assertions und das Verwahren von allem in der Versionskontrolle zusammen mit der App. Ein praktischer Mittelweg ist, zum Explorieren aufzuzeichnen und dann die nützlichen Abläufe als wartbaren Code mit passenden Selektoren und Wartezeiten neu zu schreiben.
Flakiness und Synchronisation in den Griff bekommen
Instabile Tests zerstören das Vertrauen in eine Suite. Auf echten Geräten ist das Timing tatsächlich variabel – Netzwerklatenz, Animationen und Hintergrundlast schwanken alle –, die Lösung ist also eine disziplinierte Synchronisation.
- Verwende niemals feste Wartezeiten als primäres Wartemittel. Ersetze sie durch explizite Wartungen, die eine Bedingung abfragen (Element vorhanden, sichtbar, aktiviert) bis zu einem Timeout.
- Verwende stabile Selektoren. Bevorzuge Accessibility-Identifier und Ressourcen-IDs gegenüber XPath nach Text oder Index, die bei Copy- und Layout-Änderungen brechen.
- Warte auf den App-Zustand, nicht auf die Uhr. Idle-Bedingungen, Signale für Netzwerkruhe und Element-Zustände sind zuverlässiger als eine Dauer zu erraten.
- Kontrolliere die Umgebung. Setze den App-Zustand zwischen Tests zurück, säe bekannte Daten, deaktiviere Animationen wo möglich und lege Sprache/Zeitzone fest, damit Läufe deterministisch sind.
- Isoliere und wiederhole gezielt. Isoliere bekanntermaßen instabile Tests, füge begrenzte Wiederholungen für tatsächlich nichtdeterministische Schritte hinzu und verfolge Flake-Raten, um Grundursachen zu beheben statt sie zu verdecken.
Parallelisierung über eine Flotte
Ein einzelnes Gerät führt Tests seriell aus; eine Flotte führt sie parallel aus. Das ist der Hauptgrund, gegen physische Hardware im großen Maßstab zu automatisieren.
Sharding teilt die Testmenge über Geräte auf, sodass die Gesamtlaufzeit annähernd linear mit der Geräteanzahl sinkt. Du kannst nach Test shardem (Fälle gleichmäßig verteilen) oder nach Matrixzelle (jedes Gerät übernimmt eine OS/Modell-Kombination aus deinen Abdeckungsstufen).
Praktische Anforderungen für saubere Parallelläufe:
| Aspekt | Ansatz |
|---|---|
| Geräteadressierung | Stabile Geräte-IDs/Seriennummern; eine Registry, die Geräte auf Fähigkeiten abbildet |
| Isolation | Eine Sitzung pro Gerät; App-Zustand zwischen Läufen zurücksetzen |
| Zuteilung | Ein Scheduler, der freie Geräte an Jobs verleiht und Doppelbuchungen verhindert |
| Zuverlässigkeit | Health-Checks, damit tote/offline Geräte übersprungen statt als Fehler gewertet werden |
Die Koordination von Zuteilungen, Warteschlangen und Staffelung ist Aufgabe einer Orchestrierungsschicht – siehe Scheduling und Orchestrierung. Geräte gesund genug zu halten, um den Ergebnissen zu vertrauen, wird in Flottenüberwachung und -gesundheit behandelt.
CI-Integration
Automatisierung liefert Wert, wenn sie automatisch läuft. Das typische Muster:
- Build des App-Artefakts in CI.
- Bereitstellung eines Geräts aus der Flotte über den Scheduler (ein Gerät der Core-Stufe verleihen, das zur Ziel-Matrixzelle passt).
- Installieren und ausführen der Suite auf dem geliehenen Gerät.
- Artefakte sammeln – Logs (Logcat/Syslog), Screenshots oder Video und ein strukturierter Testbericht.
- Gate der Pipeline auf die Core-Stufe; breitere Abdeckung nächtlich oder vor jedem Release laufen lassen, um das PR-Feedback schnell zu halten.
Halte die Gerätebereitstellung hinter dem Scheduler, statt Seriennummern in der Pipeline fest zu kodieren, damit CI-Jobs sich sauber einreihen, wenn Geräte belegt sind, und nie kollidieren.
Faustregel: Jeden Build mit einer kleinen, schnellen, stabilen Core-Suite absichern. Die langsame, breite Matrix in nächtliche oder Release-Läufe verschieben. Das hält das Entwickler-Feedback eng, ohne die Abdeckung zu opfern.