iOS-Biometrieregressionen mit simctl auf einem Cloud Mac testen

Security ·ca. 5 Min. Lesezeit

iOS-Biometrieregressionen mit simctl auf einem Cloud Mac testen

Die Anmeldeseite war gerade überarbeitet worden. Der Rückfall auf die Passworteingabe wurde lokal geprüft, doch niemand bemerkte, dass der Ablauf im Zweig „Biometrie nicht registriert“ nicht mehr fortgesetzt werden konnte. Erst als die Testumgebung einen älteren Simulator wiederverwendete, blieb der Prozess sporadisch hängen. Solche Probleme liegen nicht am Algorithmus, sondern daran, dass der Authentifizierungszustand im Test nicht kontrolliert wird. Auf einem Cloud Mac lassen sich Simulatorzustände, Authentifizierungsereignisse und Bereinigungsschritte als feste Pipeline abbilden, sodass jeder Commit dieselben Verzweigungen abdeckt.

Grenzen der Automatisierung vorab festlegen

Mit simctl biometric lassen sich die Zustände registriert und nicht registriert sowie erfolgreiche und fehlgeschlagene Übereinstimmungen simulieren. Damit kann geprüft werden, wie Oberfläche und Anwendungszustand auf ein empfangenes Ergebnis reagieren. Sensoren oder der tatsächliche Registrierungsvorgang lassen sich damit jedoch ebenso wenig validieren wie die Sicherheit auf Geräteebene. Das Testziel sollte auf vier Punkte begrenzt werden:

Szenario Injizierter Zustand Erwartetes Anwendungsverhalten
Erfolgreiche Authentifizierung enroll + match Geschützte Seite öffnen
Ablehnung durch den Benutzer enroll + nonmatch Auf der aktuellen Seite bleiben und einen erneuten Versuch erlauben
Noch nicht registriert unenroll Eine ausführbare Alternative anzeigen
Funktion nicht verfügbar Test-Double gibt einen Fehler zurück Keine wiederholten Dialoge anzeigen und Benutzereingaben nicht verlieren

Ein Simulatortest belegt, dass „die Anwendung das Systemergebnis korrekt verarbeitet“, nicht dass „das biometrische Merkmal selbst zuverlässig ist“.

Abnahmetests auf echten Geräten bleiben weiterhin erforderlich. Es ist jedoch nicht nötig, jede fachliche Verzweigung ausschließlich durch manuelle Bedienung zu prüfen.

Systemauthentifizierung hinter einer austauschbaren Schnittstelle kapseln

Wenn ein View-Controller den Authentifizierungskontext direkt erzeugt, können Unit-Tests nur auf den Systemdialog warten. Robuster ist eine kleine Protokollschnittstelle: Die Produktivimplementierung ruft das Systemframework auf, während die Testimplementierung ein festgelegtes Ergebnis zurückgibt.

import LocalAuthentication

protocol BiometricAuthenticating {
    func authenticate(reason: String) async throws -> Bool
}

struct SystemBiometricAuthenticator: BiometricAuthenticating {
    func authenticate(reason: String) async throws -> Bool {
        let context = LAContext()
        var error: NSError?
        guard context.canEvaluatePolicy(
            .deviceOwnerAuthenticationWithBiometrics,
            error: &error
        ) else {
            throw error ?? LAError(.biometryNotAvailable)
        }
        return try await context.evaluatePolicy(
            .deviceOwnerAuthenticationWithBiometrics,
            localizedReason: reason
        )
    }
}

Die Fachlogik erhält ausschließlich ein BiometricAuthenticating. Unit-Tests prüfen alle Fehlerzuordnungen, während in den UI-Tests nur wenige End-to-End-Fälle verbleiben. Diese bestätigen, dass nach dem Erscheinen des Systempanels die Aktionen für Erfolg, Fehlschlag und Rückfall tatsächlich zu den richtigen Seiten führen. Selbst wenn sich der Wortlaut der Systemhinweise zwischen Versionen ändert, hängt die Kernlogik damit nicht von einem fragilen Vergleich des vollständigen Textes ab.

Simulator fest zuordnen und Authentifizierungszustand steuern

Zunächst sollte geprüft werden, welche Parameter die aktuell verwendeten Werkzeuge unterstützen. So wird vermieden, dass ein Befehlsformat aus einer anderen Laufzeitumgebung ungeprüft übernommen wird:

xcrun simctl help biometric
xcrun simctl list devices available

In der Pipeline sollte der mehrdeutige Selektor booted nicht verwendet werden. Wenn parallele Jobs gleichzeitig Geräte starten, kann er auf die falsche Instanz verweisen. Stattdessen muss jeder Job eine eindeutige UDID anlegen oder zugewiesen bekommen und sie für sämtliche Befehle verwenden:

set -euo pipefail

UDID="${SIMULATOR_UDID:?missing simulator udid}"

xcrun simctl boot "$UDID" 2>/dev/null || true
xcrun simctl bootstatus "$UDID" -b
xcrun simctl biometric "$UDID" unenroll
xcrun simctl biometric "$UDID" enroll

Nach dem Start des Tests darf das Ereignis erst gesendet werden, wenn das Authentifizierungspanel tatsächlich bereit ist. Eine feste Wartezeit von zwei Sekunden versagt bei schwankender Auslastung schnell. Der Test-Build kann unmittelbar vor dem Auslösen der Authentifizierung eine eigene Markierung wie AUTH_PROMPT_READY ausgeben. Der äußere Controller beobachtet einen mit einem Timeout versehenen Logstream und führt erst nach Erkennen der Markierung die folgenden Befehle aus:

xcrun simctl biometric "$UDID" match face
xcrun simctl biometric "$UDID" nonmatch face

Je nach Laufzeitumgebung können sich die akzeptierten Parameter für den Biometrietyp unterscheiden. Die endgültigen Befehle müssen sich daher nach der lokalen Ausgabe von help biometric richten. Inkompatibilitäten sollten bereits bei der Vorabprüfung der Umgebung zum Abbruch führen und nicht erst mitten im Test auffallen.

Testfälle voneinander isolieren

Der Registrierungszustand der Biometrie gehört zum Simulator und nicht zu einer einzelnen Testmethode. Ein vom vorherigen Testfall hinterlassenes enroll verfälscht einen nachfolgenden Test für den Zustand „nicht registriert“. Deshalb sollte jedes Szenario seinen Ausgangszustand ausdrücklich setzen und ihn nach Abschluss des Tests wieder zurücksetzen:

cleanup() {
  xcrun simctl biometric "$UDID" unenroll 2>/dev/null || true
  xcrun simctl shutdown "$UDID" 2>/dev/null || true
}
trap cleanup EXIT

Nicht denselben Gerätesatz gemeinsam verwenden

Wenn mehrere Test-Shards parallel auf demselben LemonVM Cloud Mac ausgeführt werden, benötigt jeder Job ein eigenes --set-Verzeichnis oder eine vorab zugewiesene, separate UDID. Gerätesätze, DerivedData und Ergebnispakete sollten jeweils in Verzeichnissen mit der Jobkennung abgelegt werden. So kann ein Job nicht versehentlich die Geräte eines anderen Jobs löschen.

Keine Systemtexte als Assertions verwenden

Systemdialoge hängen von Systemversion, Sprache und Gerätefunktionen ab. UI-Tests sollten das Systempanel, anwendungseigene Schaltflächen und den abschließenden fachlichen Zustand prüfen, statt Systemhinweise wortwörtlich abzugleichen. Die präzise Zuordnung der Fehlertypen gehört in Unit-Tests mit einem Test-Double der Protokollschnittstelle.

Fehlernachweise und Abnahmecheckliste einrichten

Bei einem Fehlschlag sollten mindestens das Testergebnispaket, die Anwendungsprotokolle, die Ziel-UDID, die Systemversion, das Simulatormodell und der Registrierungszustand vor Beginn des Testfalls gespeichert werden. Ein einzelner Screenshot des Fehlers reicht häufig nicht aus, um zu erkennen, ob das Ereignis zu früh gesendet, das falsche Gerät ausgewählt oder der Callback von der Anwendung nicht verarbeitet wurde.

Vor einem Commit kann die Abnahme anhand der folgenden Liste erfolgen:

Der Wert dieser Struktur liegt nicht darin, lediglich einige zusätzliche Befehle auszuführen. Entscheidend ist, dass der zuvor unsichtbare Ausgangszustand der Authentifizierung zu einer kontrollierten Testeingabe wird. Sobald Eingaben, Geräte und zeitliche Abläufe protokolliert werden können, wird die Biometrieregression von einer sporadischen manuellen Prüfung zu einem reproduzierbaren technischen Prozess.

Häufig gestellte Fragen

Ersetzt simctl biometric Tests auf echten Geräten vollständig?

Nein. Der Befehl prüft Anwendungszustände, Dialogabläufe und Rückfallpfade, aber weder Sensorqualität noch den realen Registrierungsprozess. Vor einer Veröffentlichung bleibt ein Gerätetest erforderlich.

Warum erreicht ein match- oder nonmatch-Ereignis die App manchmal nicht?

Meist wurde das Ereignis vor dem sichtbaren Authentifizierungsdialog gesendet oder mehrere Jobs verwendeten denselben Simulator. Warten Sie auf ein messbares Bereitschaftssignal und vergeben Sie pro Job eine eigene UDID.

Dedizierter physischer Knoten

LemonVM Cloud Mac passend zur Laufzeit wählen

Lemon M4 und Lemon M4 Pro sind in Singapur, Tokio, Seoul, Hongkong und im Westen der USA verfügbar – mit Tages-, Wochen-, Monats- und Quartalsabrechnung.

Cloud Mac jetzt mieten