Automatisierte Tests können die App-Qualität auf verschiedene Weise verbessern. So können Sie beispielsweise Validierungen durchführen, Regressionen erkennen und die Kompatibilität prüfen. Mit einer guten Teststrategie können Sie automatisierte Tests nutzen und sich auf einen wichtigen Vorteil konzentrieren: Entwicklerproduktivität.
Teams erreichen ein höheres Produktivitätsniveau, wenn sie einen systematischen Ansatz für Tests in Verbindung mit Infrastrukturverbesserungen verwenden. So erhalten Sie zeitnah Feedback zum Verhalten des Codes. Eine gute Teststrategie umfasst Folgendes:
- Probleme werden so früh wie möglich erkannt.
- Schnelle Ausführung
- Sie erhalten klare Hinweise, wenn etwas behoben werden muss.
Auf dieser Seite erfahren Sie, welche Arten von Tests Sie implementieren sollten, wo Sie sie ausführen und wie oft.
Die Testpyramide
Tests in modernen Anwendungen lassen sich nach Größe kategorisieren. Kleine Tests konzentrieren sich nur auf einen kleinen Teil des Codes, wodurch sie schnell und zuverlässig sind. Große Tests haben einen breiten Anwendungsbereich und erfordern komplexere Setups, die schwer zu verwalten sind. Bei großen Tests ist die Wahrscheinlichkeit, Probleme zu finden, jedoch höher.
*Fidelity (Treue) bezieht sich auf die Ähnlichkeit der Testlaufzeitumgebung mit der Produktionsumgebung.

Die meisten Apps sollten viele kleine und relativ wenige große Tests haben. Die Verteilung der Tests in den einzelnen Kategorien sollte eine Pyramide bilden, wobei die zahlreichen kleinen Tests die Basis und die weniger zahlreichen großen Tests die Spitze bilden.
Kosten eines Fehlers minimieren
Eine gute Teststrategie maximiert die Produktivität von Entwicklern und minimiert gleichzeitig die Kosten für das Auffinden von Fehlern.
Sehen Sie sich ein Beispiel für eine möglicherweise ineffiziente Strategie an. Hier ist die Anzahl der Tests nach Größe nicht in einer Pyramide angeordnet. Es gibt zu viele umfangreiche End-to-End-Tests und zu wenige UI-Komponententests:

Das bedeutet, dass vor dem Zusammenführen zu wenige Tests ausgeführt werden. Wenn ein Fehler vorliegt, wird er möglicherweise erst bei den nächtlichen oder wöchentlichen End-to-End-Tests erkannt.
Es ist wichtig, die Auswirkungen auf die Kosten für das Erkennen und Beheben von Fehlern zu berücksichtigen und die Testbemühungen auf kleinere und häufigere Tests auszurichten:
- Wenn der Fehler durch einen Einheitentest erkannt wird, ist er in der Regel innerhalb von Minuten behoben. Die Kosten sind also gering.
- Bei einem End-to-End-Test kann es Tage dauern, bis derselbe Fehler gefunden wird. Dazu sind möglicherweise mehrere Teammitglieder erforderlich, was die Gesamtproduktivität verringert und die Veröffentlichung verzögern kann. Die Kosten dieses Fehlers sind höher.
Eine ineffiziente Teststrategie ist jedoch immer noch besser als gar keine. Wenn ein Fehler in die Produktion gelangt, dauert es lange, bis die Korrektur auf den Geräten der Nutzer landet, manchmal Wochen. Der Feedback-Zyklus ist also am längsten und teuersten.
Eine skalierbare Teststrategie
Die Testpyramide wurde traditionell in drei Kategorien unterteilt:
- Einheitentests
- Integrationstests
- End-to-End-Tests.
Da diese Konzepte jedoch keine genauen Definitionen haben, können Teams ihre Kategorien unterschiedlich definieren, z. B. mit fünf Ebenen:

- Ein Einheitentest wird auf dem Hostcomputer ausgeführt und überprüft eine einzelne funktionale Logikeinheit ohne Abhängigkeiten vom Android-Framework.
- Beispiel: Überprüfen von Off-by-One-Fehlern in einer mathematischen Funktion.
- Bei einem Komponententest wird die Funktionalität oder das Erscheinungsbild eines Moduls oder einer Komponente unabhängig von anderen Komponenten im System überprüft. Im Gegensatz zu Unittests erstreckt sich der Testbereich eines Komponententests auf höhere Abstraktionen über einzelnen Methoden und Klassen.
- Beispiel: Screenshot-Test für eine benutzerdefinierte Schaltfläche
- Bei einem Funktionstest wird die Interaktion von zwei oder mehr unabhängigen Komponenten oder Modulen überprüft. Feature-Tests sind größer und komplexer und werden in der Regel auf Feature-Ebene ausgeführt.
- Beispiel: UI-Verhaltenstests, mit denen die Statusverwaltung auf einem Bildschirm geprüft wird
- Bei einem Anwendungstest wird die Funktionalität der gesamten Anwendung in Form einer bereitstellbaren Binärdatei geprüft. Es handelt sich um umfangreiche Integrationstests, bei denen ein debuggbares Binärprogramm, z. B. ein Entwickler-Build, der Testhooks enthalten kann, als zu testendes System verwendet wird.
- Beispiel: UI-Verhaltenstest zur Überprüfung von Konfigurationsänderungen auf einem faltbaren Gerät, Lokalisierungs- und Barrierefreiheitstests
- Mit einem Releasekandidatentest wird die Funktionalität eines Release-Builds überprüft.
Sie ähneln Anwendungstests, mit dem Unterschied, dass das Anwendungs-Binärprogramm minimiert und optimiert wird. Dabei handelt es sich um umfangreiche End-to-End-Integrationstests, die in einer Umgebung ausgeführt werden, die der Produktionsumgebung so nahe wie möglich kommt, ohne die App öffentlichen Nutzerkonten oder öffentlichen Back-Ends auszusetzen.
- Beispiel: Wichtiges Nutzerverhalten, Leistungstests
Bei dieser Kategorisierung werden Genauigkeit, Zeit, Umfang und Isolierungsgrad berücksichtigt. Sie können verschiedene Arten von Tests für mehrere Ebenen durchführen. Die Anwendungstestebene kann beispielsweise Verhaltens-, Screenshot- und Leistungstests enthalten.
Umfang |
Netzwerkzugriff |
Umsetzung |
Build-Typ |
Lebenszyklus |
|
---|---|---|---|---|---|
Einheit |
Einzelne Methode oder Klasse mit minimalen Abhängigkeiten. |
Nein |
Lokal |
Debuggable |
Vor dem Zusammenführen |
Komponente |
Modul- oder Komponentenebene Mehrere Kurse zusammen |
Nein |
Lokal |
Debuggable |
Vor dem Zusammenführen |
Funktion |
Funktionsebene Einbindung in Komponenten, die anderen Teams gehören |
Mocked |
Lokal |
Debuggable |
Vor dem Zusammenführen |
Anwendung |
Anwendungsebene Integration mit Funktionen und/oder Diensten, die anderen Teams gehören |
Mocked |
Emulator |
Debuggable |
Vor der Zusammenführung |
Releasekandidat |
Anwendungsebene Integration mit Funktionen und/oder Diensten, die anderen Teams gehören |
Produktionsserver |
Emulator |
Minimierter Release-Build |
Nach dem Zusammenführen |
Testkategorie auswählen
Als Faustregel gilt, dass Sie die unterste Ebene der Pyramide in Betracht ziehen sollten, die dem Team das richtige Feedback geben kann.
Überlegen Sie sich beispielsweise, wie Sie die Implementierung dieser Funktion testen können: die Benutzeroberfläche eines Anmeldevorgangs. Je nachdem, was Sie testen möchten, wählen Sie unterschiedliche Kategorien aus:
Zu testendes Subjekt |
Beschreibung des Tests |
Testkategorie |
Beispiel für einen Testtyp |
---|---|---|---|
Logik für die Formularvalidierung |
Eine Klasse, die die E‑Mail-Adresse anhand eines regulären Ausdrucks validiert und prüft, ob das Passwortfeld ausgefüllt wurde. Sie hat keine Abhängigkeiten. |
Einheitentests |
|
Verhalten der Benutzeroberfläche des Anmeldeformulars |
Ein Formular mit einer Schaltfläche, die nur aktiviert wird, wenn das Formular validiert wurde |
Komponententests |
UI-Verhaltenstest, der auf Robolectric ausgeführt wird |
Darstellung der Benutzeroberfläche des Anmeldeformulars |
Ein Formular, das einer UX-Spezifikation entspricht |
Komponententests |
|
Integration in den Auth-Manager |
Die Benutzeroberfläche, die Anmeldedaten an einen Autorisierungsmanager sendet und Antworten empfängt, die verschiedene Fehler enthalten können. |
Funktionstests |
|
Anmeldedialogfeld |
Ein Bildschirm mit dem Anmeldeformular, wenn die Schaltfläche „Anmelden“ gedrückt wird. |
Anwendungstests |
UI-Verhaltenstest, der auf Robolectric ausgeführt wird |
Wichtiges Nutzerverhalten: Anmeldung |
Vollständiger Anmeldevorgang mit einem Testkonto auf einem Staging-Server |
Releasekandidat |
End-to-End-Compose-UI-Verhaltenstest, der auf dem Gerät ausgeführt wird |
In einigen Fällen kann es subjektiv sein, ob etwas zu einer bestimmten Kategorie gehört. Es kann zusätzliche Gründe dafür geben, dass ein Test nach oben oder unten verschoben wird, z. B. Infrastrukturkosten, Instabilität und lange Testzeiten.
Die Testkategorie gibt nicht den Testtyp vor und nicht alle Funktionen müssen in jeder Kategorie getestet werden.
Manuelle Tests können ebenfalls Teil Ihrer Teststrategie sein. In der Regel führen QA-Teams Release-Candidate-Tests durch, sie können aber auch in anderen Phasen beteiligt sein. Beispiel: Exploratives Testen einer Funktion ohne Skript auf Fehler.
Testinfrastruktur
Eine Teststrategie muss durch Infrastruktur und Tools unterstützt werden, damit Entwickler ihre Tests kontinuierlich ausführen und Regeln durchsetzen können, die dafür sorgen, dass alle Tests bestanden werden.
Sie können Tests nach Umfang kategorisieren, um festzulegen, wann und wo welche Tests ausgeführt werden sollen. Beispiel für das 5-Schicht-Modell:
Kategorie |
Umgebung (wo) |
Trigger (wann) |
---|---|---|
Einheit |
[Lokal][4] |
Jedes Commit |
Komponente |
Lokal |
Jedes Commit |
Funktion |
Lokal und Emulatoren |
Vor dem Zusammenführen, bevor eine Änderung zusammengeführt oder eingereicht wird |
Anwendung |
Lokal, Emulatoren, 1 Smartphone, 1 faltbares Smartphone |
Nach dem Zusammenführen oder Einreichen einer Änderung |
Releasekandidat |
8 verschiedene Smartphones, 1 faltbares Smartphone, 1 Tablet |
Vor Veröffentlichung |
- Unit- und Komponententests werden für jeden neuen Commit im Continuous Integration-System ausgeführt, aber nur für die betroffenen Module.
- Alle Unit-, Komponenten- und Funktionstests werden vor dem Zusammenführen oder Einreichen einer Änderung ausgeführt.
- Anwendungstests werden nach dem Zusammenführen ausgeführt.
- Release-Candidate-Tests werden jede Nacht auf einem Smartphone, einem faltbaren Gerät und einem Tablet ausgeführt.
- Vor einem Release werden Release-Kandidaten auf einer großen Anzahl von Geräten getestet.
Diese Regeln können sich im Laufe der Zeit ändern, wenn die Anzahl der Tests die Produktivität beeinträchtigt. Wenn Sie beispielsweise Tests auf einen nächtlichen Rhythmus umstellen, können Sie die Build- und Testzeiten für die kontinuierliche Integration verkürzen, aber auch den Feedbackzyklus verlängern.