Grundlagen zum Testen von Android-Apps

Auf dieser Seite werden die wichtigsten Grundsätze für das Testen von Android-Apps beschrieben, einschließlich der zentralen Best Practices und ihrer Vorteile.

Vorteile von Tests

Tests sind ein wesentlicher Bestandteil der App-Entwicklung. Wenn Sie Ihre App regelmäßig testen, können Sie vor der Veröffentlichung die Richtigkeit, das funktionale Verhalten und die Nutzerfreundlichkeit Ihrer App überprüfen.

Sie können Ihre App manuell testen, indem Sie sie durchlaufen. Sie können verschiedene Geräte und Emulatoren verwenden, die Systemsprache ändern und versuchen, jeden Nutzerfehler zu generieren oder jeden Nutzerablauf zu durchlaufen.

Manuelle Tests sind jedoch schwer zu skalieren und es kann leicht passieren, dass Regressionen im Verhalten Ihrer App übersehen werden. Beim automatisierten Testen werden Tools verwendet, die Tests für Sie durchführen. Das ist schneller, besser wiederholbar und liefert in der Regel früher im Entwicklungsprozess umsetzbareres Feedback zu Ihrer App.

Testtypen in Android

Mobile Anwendungen sind komplex und müssen in vielen Umgebungen gut funktionieren. Daher gibt es viele Arten von Tests.

Betreff

Je nach Thema gibt es beispielsweise verschiedene Arten von Tests:

  • Funktionstests: Macht meine App, was sie soll?
  • Leistungstests: Werden sie schnell und effizient durchgeführt?
  • Tests zur Barrierefreiheit: Funktioniert die App gut mit Bedienungshilfen?
  • Kompatibilitätstests: Funktioniert die App auf allen Geräten und API-Levels?

Umfang

Tests variieren auch je nach Größe oder Isolierungsgrad:

  • Einheitentests oder kleine Tests prüfen nur einen sehr kleinen Teil der App, z. B. eine Methode oder Klasse.
  • End-to-End-Tests oder große Tests prüfen gleichzeitig größere Teile der App, z. B. einen ganzen Bildschirm oder Nutzerfluss.
  • Mittelgroße Tests liegen dazwischen und prüfen die Integration zwischen zwei oder mehr Einheiten.
Tests können klein, mittel oder groß sein.
Abbildung 1: Testbereiche in einer typischen Anwendung.

Es gibt viele Möglichkeiten, Tests zu klassifizieren. Der wichtigste Unterschied für App-Entwickler ist jedoch, wo Tests ausgeführt werden.

Instrumentierte Tests im Vergleich zu lokalen Tests

Sie können Tests auf einem Android-Gerät oder auf einem anderen Computer ausführen:

  • Instrumentierte Tests werden auf einem Android-Gerät ausgeführt, entweder auf einem physischen oder einem emulierten Gerät. Die App wird zusammen mit einer Test-App erstellt und installiert, die Befehle einfügt und den Status liest. Instrumentierte Tests sind in der Regel UI-Tests, bei denen eine App gestartet und dann mit ihr interagiert wird.
  • Lokale Tests werden auf Ihrem Entwicklungscomputer oder einem Server ausgeführt. Daher werden sie auch als Host-seitige Tests bezeichnet. Sie sind in der Regel klein und schnell und isolieren das zu testende Element vom Rest der App.
Tests können als instrumentierte Tests auf einem Gerät oder als lokale Tests auf Ihrem Entwicklungscomputer ausgeführt werden.
Abbildung 2: Verschiedene Arten von Tests, je nachdem, wo sie ausgeführt werden.

Nicht alle Unit-Tests sind lokal und nicht alle End-to-End-Tests werden auf einem Gerät ausgeführt. Beispiel:

  • Umfangreicher lokaler Test: Sie können einen lokal ausgeführten Android-Simulator wie Robolectric verwenden.
  • Kleiner instrumentierter Test: Sie können überprüfen, ob Ihr Code gut mit einer Framework-Funktion wie einer SQLite-Datenbank funktioniert. Sie können diesen Test auf mehreren Geräten ausführen, um die Integration mit mehreren Versionen von SQLite zu prüfen.

Beispiele

Die folgenden Snippets zeigen, wie Sie in einem instrumentierten UI-Test mit der Benutzeroberfläche interagieren, indem Sie auf ein Element klicken und prüfen, ob ein anderes Element angezeigt wird.

Espresso

// When the Continue button is clicked
onView(withText("Continue"))
    .perform(click())

// Then the Welcome screen is displayed
onView(withText("Welcome"))
    .check(matches(isDisplayed()))

Compose-Benutzeroberfläche

// When the Continue button is clicked
composeTestRule.onNodeWithText("Continue").performClick()

// Then the Welcome screen is displayed
composeTestRule.onNodeWithText("Welcome").assertIsDisplayed()

Dieses Snippet zeigt einen Teil eines Einheitstests für ein ViewModel (lokaler Test auf Hostseite):

// Given an instance of MyViewModel
val viewModel = MyViewModel(myFakeDataRepository)

// When data is loaded
viewModel.loadData()

// Then it should be exposing data
assertTrue(viewModel.data != null)

Testbare Architektur

Bei einer testbaren App-Architektur folgt der Code einer Struktur, die es Ihnen ermöglicht, verschiedene Teile davon einfach isoliert zu testen. Testbare Architekturen haben auch andere Vorteile, z. B. eine bessere Lesbarkeit, Wartbarkeit, Skalierbarkeit und Wiederverwendbarkeit.

Eine Architektur, die nicht testbar ist, führt zu Folgendem:

  • Größere, langsamere und instabilere Tests. Klassen, die nicht als Unit-Tests getestet werden können, müssen möglicherweise durch größere Integrationstests oder UI-Tests abgedeckt werden.
  • Weniger Möglichkeiten, verschiedene Szenarien zu testen. Größere Tests sind langsamer. Daher ist es möglicherweise unrealistisch, alle möglichen Status einer App zu testen.

Weitere Informationen zu Architekturrichtlinien finden Sie im Leitfaden zur App-Architektur.

Methoden zur Entkopplung

Wenn Sie einen Teil einer Funktion, Klasse oder eines Moduls vom Rest trennen können, ist das Testen einfacher und effektiver. Diese Vorgehensweise wird als Entkopplung bezeichnet und ist das wichtigste Konzept für eine testbare Architektur.

Häufig verwendete Entkopplungstechniken sind:

  • Teilen Sie eine App in Ebenen wie Präsentation, Domain und Daten auf. Sie können eine App auch in Module aufteilen, eines pro Funktion.
  • Fügen Sie Entitäten mit vielen Abhängigkeiten, z. B. Aktivitäten und Fragmenten, keine Logik hinzu. Verwenden Sie diese Klassen als Einstiegspunkte für das Framework und verschieben Sie die UI- und Geschäftslogik an einen anderen Ort, z. B. in ein Composable, ein ViewModel oder eine Domänenebene.
  • Vermeiden Sie direkte Framework-Abhängigkeiten in Klassen, die Geschäftslogik enthalten. Verwenden Sie beispielsweise keine Android-Kontexte in ViewModels.
  • Abhängigkeiten lassen sich leicht ersetzen. Verwenden Sie beispielsweise Schnittstellen anstelle konkreter Implementierungen. Verwenden Sie die Abhängigkeitsinjektion, auch wenn Sie kein DI-Framework verwenden.

Nächste Schritte

Nachdem Sie nun wissen, warum Sie Tests durchführen sollten und welche zwei Haupttypen von Tests es gibt, können Sie sich mit dem Thema Was sollte getestet werden? befassen oder mehr über Teststrategien erfahren.

Wenn Sie Ihren ersten Test erstellen und dabei lernen möchten, können Sie sich auch die Codelabs zum Testen ansehen.