Testen mobiler Apps: Emulatoren, Simulatoren und echte Geräte

Du hast gerade deine mobile App fertig gebaut. Sie läuft perfekt auf deinem Laptop, der Build ist signiert und bereit. Du fühlst dich gut dabei, sie in den Store zu bringen. Aber hier ist die unangenehme Wahrheit: Dein Laptop ist nicht das Telefon deiner Nutzer. Nicht einmal annähernd.

Nutzer führen deine App auf Hunderten verschiedenen Geräten aus. Unterschiedliche Bildschirmgrößen, OS-Versionen, Akkustände, Netzwerkbedingungen und Hardwarekonfigurationen. Ein Fehler, der auf deinem Entwicklungsrechner nie auftritt, kann die App auf einem bestimmten Telefonmodell zum Absturz bringen. Ein einziger schlechter Release kann deine Store-Bewertung ruinieren und über Nacht Nutzer kosten.

Das Testen mobiler Apps ist keine Option. Aber wie du testest und wo du diese Tests ausführst, macht einen großen Unterschied darin, wie viel Vertrauen du vor der Veröffentlichung tatsächlich gewinnst.

Die relevanten Testebenen

Mobiles Testen ist nicht eine Sache. Es ist ein Stapel von Ebenen, die jeweils verschiedene Arten von Problemen mit unterschiedlicher Geschwindigkeit abfangen.

Unit-Tests bilden die unterste Ebene. Sie überprüfen, ob ein einzelnes Verhalten korrekt funktioniert. Im mobilen Kontext bedeutet das, von einem sinnvollen Einstiegspunkt aus zu testen: Reagiert das ViewModel korrekt, wenn der Nutzer einen Button drückt? Liefert der Use Case die richtige Ausgabe für eine bestimmte Eingabe? Du testest keine internen Implementierungsdetails. Du testest beobachtbares Verhalten. Unit-Tests sind schnell, oft im Millisekundenbereich. Du kannst sie bei jeder Codeänderung in deiner Pipeline mit einem Emulator oder Simulator auslösen. Kein physisches Gerät nötig.

Integrationstests sitzen eine Ebene höher. Sie prüfen, wie Komponenten zusammenarbeiten. Werden die Daten von der API tatsächlich korrekt auf dem Bildschirm angezeigt? Funktioniert der lokale Speicher, nachdem sich der Nutzer angemeldet hat? Diese Tests benötigen eine Umgebung, die einem echten Gerät ähnelt. Emulatoren, Simulatoren oder echte Geräte funktionieren hier, je nachdem, was du integrierst.

UI-Tests sitzen ganz oben. Sie simulieren echte Benutzerinteraktionen: Buttons drücken, Formulare ausfüllen, Listen scrollen und überprüfen, ob die erwarteten Elemente auf dem Bildschirm erscheinen. Diese Tests kommen der tatsächlichen Benutzererfahrung am nächsten. Sie sind auch die langsamsten und anfälligsten. Eine kleine Layoutänderung kann sie zerstören. Aber wenn sie bestehen, weißt du, dass die App aus Benutzersicht funktioniert.

Jede Ebene hat ihren Platz. Unit-Tests geben schnelles Feedback. Integrationstests finden Verdrahtungsprobleme. UI-Tests validieren die Erfahrung. Du brauchst alle drei, aber du musst nicht alle bei jedem Auslöser ausführen.

Emulatoren und Simulatoren: Schnell, aber nicht perfekt

Emulatoren (Android) und Simulatoren (iOS) sind die Arbeitspferde des mobilen Testens. Sie sind kostenlos, einfach in einer CI/CD-Pipeline zu starten und für die meisten Logik- und Layoutprüfungen gut genug.

Du kannst Unit-Tests, Integrationstests und sogar UI-Tests auf ihnen ausführen. Sie starten schnell, unterstützen verschiedene OS-Versionen und lassen dich verschiedene Bildschirmgrößen simulieren. Für die tägliche Entwicklung und interne Builds sind sie normalerweise ausreichend.

Aber sie haben einen blinden Fleck. Emulatoren und Simulatoren reproduzieren kein reales Geräteverhalten. Die Leistung ist anders. Der Akkuverbrauch ist anders. Die Sensorreaktionen sind anders. Das Netzwerkverhalten bei Mobilfunk ist anders. Ein Test, der auf einem Emulator perfekt läuft, kann auf einem physischen Gerät aufgrund von Timing, Speicherdruck oder hardwarespezifischen Eigenheiten fehlschlagen.

Um dies praktisch zu machen, hier ein GitHub Actions-Job, der einen Android-Emulator erstellt, auf seinen Start wartet, instrumentierte Tests ausführt und die Ergebnisse sammelt:

name: Android Instrumented Tests

on: [push]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Set up JDK 17
        uses: actions/setup-java@v4
        with:
          java-version: '17'
          distribution: 'temurin'

      - name: Create and start emulator
        run: |
          echo "no" | avdmanager create avd -n testDevice -k "system-images;android-33;google_apis;x86_64" --force
          $ANDROID_HOME/emulator/emulator -avd testDevice -no-window -no-audio &

      - name: Wait for emulator to boot
        run: |
          adb wait-for-device
          adb shell settings put global window_animation_scale 0.0
          adb shell settings put global transition_animation_scale 0.0
          adb shell settings put global animator_duration_scale 0.0

      - name: Run instrumented tests
        run: ./gradlew connectedCheck

      - name: Upload test results
        if: always()
        uses: actions/upload-artifact@v4
        with:
          name: test-results
          path: app/build/reports/androidTests/connected/

Wenn du nur auf Emulatoren testest, lieferst du mit unvollständigen Informationen aus.

Device Farms: Echte Hardware im großen Maßstab

Hier kommen Device Farms ins Spiel. Ein Device Farm ist ein Dienst, der dir Zugang zu echten Telefonen und Tablets in einem Rechenzentrum gibt. Du lädst deine App hoch, führst deine Tests auf Dutzenden von Geräten gleichzeitig aus und erhältst einen Bericht, der zeigt, was auf jedem Gerät bestanden hat und was kaputt gegangen ist.

Beliebte Optionen sind Firebase Test Lab für Android und iOS sowie AWS Device Farm. Diese Dienste unterstützen verschiedene Gerätemodelle, OS-Versionen und Bildschirmgrößen. Du kannst sie direkt in deine CI/CD-Pipeline integrieren. Jedes Mal, wenn ein Build abgeschlossen ist, löst die Pipeline Tests auf echter Hardware aus, bevor die App jemals den Store erreicht.

Device Farms fangen Probleme, die Emulatoren übersehen. Abstürze auf bestimmter Hardware, Layoutprobleme bei ungewöhnlichen Bildschirmverhältnissen, Leistungseinbußen auf älteren Geräten. Sie liefern dir auch Screenshots und Logs von jedem Testlauf, was die Diagnose von Fehlern erleichtert.

Aber Device Farms sind nicht kostenlos. Sie kosten Geld pro Testlauf, und die Tests dauern länger als Emulatortests. Du willst nicht jeden einzelnen Build durch einen Device Farm laufen lassen. Das wäre langsam und teuer.

Wann du was verwendest

Die Entscheidung ist praktisch, nicht ideologisch. Verwende Emulatoren und Simulatoren für schnelles Feedback während der Entwicklung und für interne Builds. Verwende Device Farms strategisch vor Releases.

Das folgende Flussdiagramm fasst die empfohlene Umgebung für jeden Testtyp basierend auf Geschwindigkeits- und Genauigkeitsanforderungen zusammen:

flowchart TD A[Testtyp] --> B{Unit-Test?} B -->|Ja| C[Emulator / Simulator] B -->|Nein| D{Integrationstest?} D -->|Ja| E[Emulator / Simulator] D -->|Nein| F{End-to-End-Test?} F -->|Ja| G{Release Candidate?} G -->|Ja| H[Device Farm] G -->|Nein| I[Emulator / Simulator] F -->|Nein| J[Manuell oder explorativ] C --> K[Schnelles Feedback, geringe Genauigkeit] E --> K I --> K H --> L[Langsamer, hohe Genauigkeit] J --> M[Echte Geräte bevorzugt]

Hier ist eine einfache Faustregel:

  • Jeder Commit: Führe Unit-Tests auf dem Emulator oder Simulator aus.
  • Jeder Pull Request: Führe Unit-Tests plus Integrationstests auf dem Emulator oder Simulator aus.
  • Vor einer gestaffelten Einführung oder einem phasenweisen Release: Führe die vollständige Testsuite auf einem Device Farm aus, die eine repräsentative Auswahl von Geräten abdeckt.

Der Schlüssel ist, die Testintensität an das Risiko anzupassen. Eine kleine Fehlerbehebung in einer internen Funktion benötigt keinen vollständigen Device Farm-Durchlauf. Ein Release, der Tausende von Nutzern erreicht, auf jeden Fall.

Eine praktische Checkliste vor der Store-Einreichung

Bevor du auf den Senden-Button in deinem App-Store-Dashboard drückst, gehe diese kurze Checkliste durch:

  • Unit-Tests bestehen auf Emulator oder Simulator für die Ziel-OS-Versionen.
  • Integrationstests bestehen für die Hauptnutzerflüsse (Anmeldung, Datenanzeige, Navigation).
  • UI-Tests bestehen auf mindestens einem Emulator und einem physischen Gerät.
  • Device Farm-Tests bestehen für die Top 5-10 Gerätemodelle, die deine Analysen zeigen, die Nutzer tatsächlich haben.
  • Keine Crash- oder ANR-Berichte (Application Not Responding) vom Device Farm-Durchlauf.
  • Screenshots vom Device Farm entsprechen den erwarteten Layouts auf verschiedenen Bildschirmgrößen.

Diese Checkliste ist nicht vollständig, aber sie fängt die häufigsten Probleme, die bis in die Produktion durchrutschen.

Die konkrete Erkenntnis

Nur auf Emulatoren zu testen ist, wie ein Auto auf einem Parkplatz Probe zu fahren. Es sagt dir, dass die Lenkung funktioniert, aber es sagt dir nicht, wie sich das Auto auf der Autobahn verhält. Device Farms liefern dir Autobahndaten. Verwende Emulatoren für Geschwindigkeit und Device Farms für Vertrauen. Automatisiere beides in deiner Pipeline, und du wirst weniger Fehler ausliefern und nachts besser schlafen.