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: die Produktivität von Entwicklern.
Teams erzielen eine höhere Produktivität, 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.
- Wird schnell ausgeführt.
- 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.
Android-Kenntnisse
Auf GitHub ansehenTeststrategie erstellen
android skills add testing-setupDie Testpyramide
Sie können Tests in modernen Anwendungen nach Größe kategorisieren. Kleine Tests konzentrieren sich nur auf einen kleinen Teil des Codes und sind daher schnell und zuverlässig. Große Tests haben einen breiten Umfang und erfordern komplexere Setups, die schwer zu verwalten sind. Bei großen Tests ist die Genauigkeit jedoch höher und es können viel mehr Probleme auf einmal erkannt werden.
*Fidelity 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.
Hier ein Beispiel für eine möglicherweise ineffiziente Strategie: Hier ist die Anzahl der Tests nach Größe nicht in einer Pyramide organisiert. Es gibt zu viele große 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 Unit-Test 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 möglicherweise zu einer Verzögerung der Veröffentlichung führt. 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 Unittest wird auf dem Hostcomputer ausgeführt und prü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 Oberflächenbereich 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 umfangreicher und komplexer und werden in der Regel auf Feature-Ebene ausgeführt.
- Beispiel: Tests zum Verhalten der Benutzeroberfläche, mit denen die Statusverwaltung auf einem Bildschirm überprüft wird
- Bei einem Anwendungstest wird die Funktionalität der gesamten Anwendung in Form eines bereitstellbaren Binärprogramms geprüft. Es handelt sich um große 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 Bedienungshilfentests
- Bei einem Releasekandidaten wird die Funktionalität eines Release-Builds getestet.
Sie ähneln Anwendungstests, mit dem Unterschied, dass die Anwendungsbinärdatei minifiziert und optimiert ist. 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: Kritische User Journeys, Leistungstests
Bei dieser Kategorisierung werden Genauigkeit, Zeit, Umfang und Isolierungsgrad berücksichtigt. Sie können verschiedene Arten von Tests für mehrere Ebenen haben. Die Anwendungstestebene kann beispielsweise Verhaltens-, Screenshot- und Leistungstests enthalten.
Umfang |
Netzwerkzugriff |
Ausführung |
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 |
Feature |
Funktionsebene Integration mit 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 |
Simuliert |
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 der Zusammenführung |
Testkategorie auswählen
Als Faustregel gilt, dass Sie die unterste Ebene der Pyramide berücksichtigen 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 des Formularvalidators |
Eine Klasse, die die E‑Mail-Adresse anhand eines regulären Ausdrucks validiert und prüft, ob das Passwortfeld ausgefüllt wurde. Es hat keine Abhängigkeiten. |
Einheitentests |
|
Verhalten der Benutzeroberfläche des Anmeldeformulars |
Ein Formular mit einem Button, der nur aktiviert wird, wenn das Formular validiert wurde |
Komponententests |
UI-Verhaltenstest, der mit 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, über die Anmeldedaten an einen Autorisierungsmanager gesendet und Antworten empfangen werden, die verschiedene Fehler enthalten können. |
Funktionstests |
|
Dialogfeld zur Anmeldung |
Ein Bildschirm mit dem Anmeldeformular, wenn die Schaltfläche „Anmelden“ gedrückt wird. |
Anwendungstests |
UI-Verhaltenstest, der mit Robolectric ausgeführt wird |
Critical User Journey: 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. Normalerweise führen QA-Teams Release-Kandidatentests durch, sie können aber auch in anderen Phasen beteiligt sein. Beispiel: Exploratives Testen einer Funktion auf Fehler ohne Script.
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 (wenn) |
|---|---|---|
Einheit |
[Lokal][4] |
Jedes Commit |
Komponente |
Lokal |
Jedes Commit |
Feature |
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 Candidate-Tests auf einer großen Anzahl von Geräten ausgeführt.
Diese Regeln können sich im Laufe der Zeit ändern, wenn sich die Anzahl der Tests auf die Produktivität auswirkt. 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.