iOS App Intents auf einem Cloud-Mac zuverlässig testen

KI-Automatisierung ·ca. 5 Min. Lesezeit

iOS App Intents auf einem Cloud-Mac zuverlässig testen

Ein Kurzbefehl zum „Lesen erfassen“ ist auf dem Entwicklungsrechner auffindbar, erscheint aber im Simulator eines Remote-Builds nicht. Ändern Sie deshalb nicht sofort den Anwendungscode: Ob die Parameter gültig sind, ob sich der Intent ausführen lässt und ob das System die Aktion findet, sind drei getrennte Prüfungen. Ein Cloud-Mac eignet sich für eine feste Testumgebung für die ersten beiden Punkte. Den letzten Punkt müssen Sie weiterhin in einem Simulator mit installierter App prüfen.

Grenzen automatisierter Tests festlegen

Dieser Artikel prüft den Ablauf anhand einer Beispielaktion, die nichts auf die Festplatte schreibt: Sie nimmt eine Buch-ID entgegen, entfernt Leerraum am Anfang und Ende und gibt die normalisierte ID zurück. So lassen sich Speicherberechtigungen und Netzwerkschwankungen zunächst als Fehlerquellen ausschließen. Wenn später eine Datenbank hinzukommt, testen Sie Schreibvorgänge und das Verhalten bei wiederholter Ausführung gesondert. Verwechseln Sie „erfolgreich zurückgegeben“ nicht mit „Daten gespeichert“.

Die Abnahme erfolgt auf drei Ebenen: Reine Swift-Tests prüfen leere Werte und unzulässige Zeichen; XCTest ruft perform() auf und prüft Rückgabewert und Fehler; im Simulator wird manuell kontrolliert, ob die Aktion sichtbar ist, sich Parameter eingeben lassen und das Ergebnis lesbar ist. Fehler auf den ersten beiden Ebenen sollten einen Merge verhindern. Die dritte Ebene hängt von der Systemindizierung ab. Sie eignet sich daher als Prüfung vor einem Release, nicht als Test mit einer fest einprogrammierten Wartezeit.

Deinstallieren und installieren Sie die App in automatisierten Tests nicht immer wieder neu, nur um auf das Erscheinen des Kurzbefehls zu warten. Belegen Sie zuerst, dass der Codevertrag stimmt, und untersuchen Sie danach Installation, ersten Start und Erkennung durch das System.

Eingaberegeln als direkt testbaren Typ auslagern

Die folgende Regel akzeptiert 1–32 ASCII-Buchstaben, Ziffern, Unterstriche und Bindestriche. Leerraum ist nur am Anfang und Ende der Eingabe zulässig; andere Zeichen führen zu einem eindeutigen Fehler. perform() gibt in diesem Beispiel lediglich die ID zurück und hat keine persistierenden Nebenwirkungen.

import AppIntents
import Foundation

enum ReadingIDError: LocalizedError {
    case invalid

    var errorDescription: String? {
        "编号须为 1–32 位字母、数字、下划线或连字符"
    }
}

enum ReadingID {
    static func normalize(_ raw: String) throws -> String {
        let value = raw.trimmingCharacters(in: .whitespacesAndNewlines)
        let pattern = #"^[A-Za-z0-9_-]{1,32}$"#
        guard value.range(of: pattern, options: .regularExpression) != nil else {
            throw ReadingIDError.invalid
        }
        return value
    }
}

struct CheckReadingIDIntent: AppIntent {
    static var title: LocalizedStringResource = "检查书籍编号"
    static var openAppWhenRun = false

    @Parameter(title: "书籍编号")
    var bookID: String

    func perform() async throws -> some IntentResult & ReturnsValue<String> {
        let normalized = try ReadingID.normalize(bookID)
        return .result(value: normalized)
    }
}

Nehmen Sie Parametertitel, Aktionstitel und Fehlermeldung in die Lokalisierungsressourcen des Projekts auf. Die chinesischen Texte hier sind Beispieltexte und dürfen in einer mehrsprachigen App nicht unverändert als Texte für alle Sprachen ausgeliefert werden. Die Regel selbst akzeptiert nur ASCII-IDs. Wenn Ihre Anwendung chinesische Schriftzeichen oder andere Zeichen zulässt, definieren Sie zunächst den erlaubten Zeichensatz und passen Sie dann Ausdruck und Testfälle an.

Grenzfälle statt nur gültiger Eingaben testen

Prüfen Sie mindestens, dass " book_7 " den Wert "book_7" ergibt und dass eine leere Zeichenfolge, Leerzeichen innerhalb der ID sowie IDs mit mehr als 32 Zeichen abgewiesen werden. Prüfen Sie im Fehlerfall den Fehlertyp, nicht nur, dass „irgendein Fehler“ geworfen wurde. Sonst könnte auch ein unerwarteter Fehler aus einer zugrunde liegenden Abhängigkeit den Test bestehen lassen. Prüfen Sie bei Tests von perform() außerdem, ob der Rückgabewert der Normalisierungsregel entspricht. Halten Sie Tests der reinen Regel und Tests des Intent-Aufrufs getrennt. Nur so lässt sich bei einem Fehlschlag erkennen, ob sich die Eingaberegel oder die Anbindung an die Systemschnittstelle geändert hat.

Registrierung und Anzeige im Simulator prüfen

Soll das System eine Aktion als Vorschlag anzeigen, können Sie im App-Target einen AppShortcutsProvider hinzufügen. Der Platzhalter für den App-Namen bleibt in der Phrase stehen, damit das System die Aktion der aktuellen App zuordnet; es handelt sich nicht um einen Shell-String.

import AppIntents

struct ReadingShortcuts: AppShortcutsProvider {
    static var appShortcuts: [AppShortcut] {
        AppShortcut(
            intent: CheckReadingIDIntent(),
            phrases: ["在 \(.applicationName) 检查书籍编号"],
            shortTitle: "检查书籍编号",
            systemImageName: "book"
        )
    }
}

Prüfen Sie zuerst, ob diese Datei zum App-Target gehört und nicht nur zum Test-Target. Installieren Sie den Build und starten Sie die App einmal. Öffnen Sie anschließend im Simulator die Kurzbefehle-App, suchen Sie nach dem Aktionstitel, geben Sie eine gültige ID ein und führen Sie die Aktion aus. Geben Sie danach eine ungültige ID ein und prüfen Sie, ob die Fehlermeldung verständlich ist. Falls die Aktion nicht erscheint, halten Sie die Systemversion, die Build-Version der App und die Abfolge der Schritte nach der Installation fest. Dokumentieren Sie „erschien zufällig nach erneutem Öffnen der Ansicht“ nicht als verlässliche Lösung.

Testgerät und Ergebnisverzeichnis festlegen

Rufen Sie auf einem Cloud-Mac von ZSHMac zunächst xcrun simctl list devices available auf, um die installierten und verfügbaren Simulatoren zu sehen. Wählen Sie eine Geräte-UDID und setzen Sie SIM_UDID. Der folgende Befehl setzt voraus, dass das Projekt ein freigegebenes Scheme namens Reader enthält; verwenden Sie bei der tatsächlichen Ausführung das Scheme Ihres Projekts. Weisen Sie dem Ergebnis-Bundle bei jedem Lauf einen neuen Pfad zu, damit der Testbefehl nicht wegen einer bereits vorhandenen Datei sofort fehlschlägt.

mkdir -p artifacts
test -n "${SIM_UDID:-}" || { printf '%s\n' 'SIM_UDID is required' >&2; exit 1; }
result="$PWD/artifacts/app-intents-$(date +%Y%m%d-%H%M%S)-$$.xcresult"
xcodebuild test \
  -scheme Reader \
  -destination "platform=iOS Simulator,id=$SIM_UDID" \
  -resultBundlePath "$result"

Bewahren Sie in CI sowohl den Exit-Code des Befehls als auch das Ergebnis-Bundle auf: Der Exit-Code entscheidet, ob der Job bestanden hat; das Bundle hilft bei der Suche nach dem fehlgeschlagenen Testfall. Ist das Scheme nicht freigegeben oder der gewählte Simulator nicht verfügbar, korrigieren Sie zuerst die Testkonfiguration, statt den Fehler als Problem der Intent-Logik einzuordnen. Halten Sie bei der manuellen Abnahme fest, ob die Aktion erscheint, ob die Eingabeaufforderung stimmt und wie sich gültige und ungültige Parameter tatsächlich verhalten.

Fehler nach Ebenen eingrenzen

Symptom Zuerst prüfen Nicht als Erstes tun
Test der reinen Regel schlägt fehl Zeichensatz, Länge und Behandlung von Leerraum am Anfang und Ende Simulator neu installieren
Ergebnis von perform() stimmt nicht Parameterübergabe und Typ des Rückgabewerts Auf die Systemindizierung warten
Testbefehl findet kein Gerät Liste verfügbarer Geräte und UDID Swift-Regel ändern
Aktion fehlt in Kurzbefehle Target-Zugehörigkeit der Datei, Installation und erster App-Start Feste Wartezeit zum Test hinzufügen
Aktion ist vorhanden, schlägt aber bei der Ausführung fehl Parameterhinweis, Fehlertyp und Version des Zielsystems Alle Fehler unterdrücken

Diese Prüfung nach Ebenen grenzt die Fehlerursache ein. Sie garantiert nicht, dass der Systemeintrag unmittelbar nach der Installation sichtbar ist. Die Abnahme ist erst abgeschlossen, wenn die Codetests bestanden sind und die Aktion im Simulator sowohl mit gültiger als auch mit ungültiger Eingabe geprüft wurde. Sobald echte Schreibvorgänge hinzukommen, brauchen Sie zusätzliche Tests für wiederholte Ausführung und dauerhaft gespeicherte Daten. Der Erfolgsmaßstab dieses Beispiels, das nur eine ID zurückgibt, reicht dann nicht mehr aus.

Häufig gestellte Fragen

Warum fehlt die Aktion in Kurzbefehle, obwohl XCTest erfolgreich war?

Prüfen Sie, ob die App mit ihrem AppShortcutsProvider installiert und gestartet wurde. Kontrollieren Sie außerdem Systemversion und Target-Konfiguration; die Indizierung kann verzögert sein.

Wo sollte die Parameterprüfung implementiert werden?

Legen Sie wiederverwendbare Regeln in einem eigenen Swift-Typ ab und rufen Sie ihn aus perform() auf. So bleibt der Unit-Test unabhängig von der Systemindizierung.

Reicht ein CI-Lauf ohne grafische Oberfläche aus?

Nein. CI prüft Eingaben und Rückgabewerte; Sichtbarkeit der Aktion und Parametereingabe müssen auf einem Simulator oder Gerät mit der Zielsystemversion kontrolliert werden.

Sie brauchen einen exklusiven Mac in der Cloud?

Wählen Sie Modell, Standort und Abrechnungszeitraum. Sie erhalten einen exklusiven physischen Mac. Die tatsächliche Verfügbarkeit sehen Sie live in der Konsole.

Konfiguration ansehen und bestellen