MangoVM Engineering-Leitfaden

XCTestPlan-Drift auf einem Cloud-Mac prüfen

XCTestPlan-Drift auf einem Cloud-Mac prüfen

Wenn derselbe Commit auf dem Rechner eines Entwicklers alle Tests durchläuft, auf einem Cloud-Mac jedoch nur einen Teil davon ausführt, liegt die häufigste Ursache nicht im Testcode. Meist ist die .xctestplan-Datei unbemerkt abgewichen: Jemand hat in Xcode vorübergehend Testfälle übersprungen, Diagnoseoptionen deaktiviert oder Umgebungsvariablen gespeichert, die nur auf dem eigenen Rechner funktionieren. Behandeln Sie XCTestPlan deshalb als Build-Eingabe und nicht als ergänzende Einstellung der grafischen Oberfläche.

Zuerst die Grenzen des Testvertrags festlegen

Ein reproduzierbarer Testeinstieg umfasst mindestens ein freigegebenes Scheme, einen XCTestPlan, ein Ausführungsziel und die Befehlszeilenargumente. Prüfen Sie zunächst, ob Scheme und Testplan tatsächlich über die Befehlszeile gefunden werden:

WORKSPACE="${WORKSPACE:-App.xcworkspace}"
SCHEME="${SCHEME:-App}"

xcodebuild \
  -workspace "$WORKSPACE" \
  -scheme "$SCHEME" \
  -showTestPlans

Wenn der erwartete Plan nicht in der Ausgabe erscheint, prüfen Sie zuerst, ob das Scheme als Shared markiert ist, die Plandatei zum Repository gehört und die Test-Aktion des Schemes auf diesen Plan verweist. Ergänzen Sie keinen fehlenden Plan provisorisch über CI-Parameter. Andernfalls driften der lokale Einstieg und die Pipeline weiter auseinander.

Folgende Punkte des Plans sollten ausdrücklich geprüft werden:

Element Zu bestätigender Sachverhalt Typische Drift
Test Targets Welche Unit- und UI-Tests ausgeführt werden Neues Target wurde nicht hinzugefügt
Selected Tests Ob nur ausgewählte Testfälle ausgeführt werden Debug-Auswahl wurde eingecheckt
Skipped Tests Ob jeder übersprungene Test einen Verantwortlichen und eine Frist hat Fehlgeschlagener Test bleibt dauerhaft verborgen
Configurations Sprache, Region und Startargumente Lokale Konfiguration überschreibt die Standardkonfiguration
Diagnostics Strategie für Absturz-, Thread- und Leistungsdiagnosen Zur Beschleunigung versehentlich deaktiviert
Parallelization Welche Targets parallel ausgeführt werden dürfen Tests mit gemeinsamem Zustand stören sich gegenseitig

Einen Test zu überspringen ist keine Fehlerbehebung. Jeder neu hinzugefügte übersprungene Test sollte wie eine Codeänderung geprüft werden und klare Bedingungen für seine Reaktivierung enthalten.

Lesbare, normalisierte Diffs erzeugen

XCTestPlan ist ein strukturiertes Dateiformat. Bei der direkten Prüfung des Rohtexts lenken die Reihenfolge der Felder und automatisch erzeugte Kennungen leicht von den relevanten Änderungen ab. Speichern Sie deshalb eine normalisierte Baseline im Repository, aus der nur Konfigurationskennungen entfernt werden, die keine Auswirkungen auf die Ausführungssemantik haben:

PLAN="App.xctestplan"
CURRENT=".ci/xctestplan.current.json"
BASELINE=".ci/xctestplan.baseline.json"

mkdir -p .ci

plutil -convert json -o - "$PLAN" |
  jq -S 'del(.configurations[]?.id)' > "$CURRENT"

diff -u "$BASELINE" "$CURRENT"

Prüfen Sie bei der erstmaligen Einrichtung $CURRENT manuell, kopieren Sie die Datei anschließend als Baseline und committen Sie sie. Bei späteren Pipeline-Läufen wird nur noch die aktuelle Datei erzeugt und mit diff verglichen. Targets, übersprungene Tests, Umgebungsvariablen, Argumente und Diagnoseoptionen müssen vollständig erhalten bleiben. Entfernen Sie keine fachlich relevanten Felder, nur um einen „sauberen Diff“ zu erhalten.

Auch das Normalisierungsskript gehört zur Testinfrastruktur. Änderungen am Skript und am Plan sollten im selben Merge Request sichtbar sein. Andernfalls kann bereits eine einzige gelockerte Filterregel dazu führen, dass jede spätere Drift unsichtbar bleibt.

Sensible Werte und Host-Abhängigkeiten abfangen

Plandateien eignen sich zum Speichern von Variablennamen, nicht jedoch für Token, Passwörter, private Schlüssel oder Entwicklerverzeichnisse. Extrahieren Sie zunächst rekursiv alle aktivierten Umgebungsvariablen:

plutil -convert json -o - App.xctestplan |
  jq -r '
    .. |
    objects |
    .environmentVariableEntries? // empty |
    .[]? |
    select(.enabled == true) |
    [.key, .value] |
    @tsv
  '

Achten Sie bei der Prüfung der Ausgabe besonders auf drei Arten von Einträgen: lange Zeichenfolgen, die wie Schlüssel aussehen, absolute Pfade nach dem Muster /Users/Name/ sowie Pfade zu Werkzeugen, die nur in einer interaktiven Shell verfügbar sind. Tatsächliche Geheimnisse sollten zur Laufzeit aus der kontrollierten CI-Umgebung injiziert werden. Der Testcode liest lediglich die Variablennamen und gibt eine eindeutige Fehlermeldung aus, wenn ein Wert fehlt.

Unkontrollierte Überschreibungsprioritäten vermeiden

XCTestPlan, Scheme, xcodebuild-Argumente und Testcode können jeweils Startargumente festlegen. Definieren Sie daher eine eindeutige Priorität: Der Plan enthält stabile Standardwerte, die CI injiziert ausschließlich sensible Werte und Kennungen des aktuellen Laufs, und der Testcode verändert keine prozessweiten Einstellungen. Wenn die Pipeline -only-testing oder -skip-testing verwendet, müssen diese Argumente in einem prüfbaren Skript stehen. Sie dürfen nicht in einem temporären Eingabefeld der Job-Oberfläche verborgen sein.

Mit einem festen Ziel ausführen und Nachweise sichern

Wählen Sie zunächst mit xcrun simctl list devices available ein Gerät aus, das auf dem aktuellen Knoten installiert ist, und übergeben Sie dessen UDID als Pipeline-Eingabe. Ein festgelegtes Gerät mit definierter Runtime macht Abweichungen leichter nachvollziehbar als eine vage Auswahl des „neuesten Systems“.

DEVICE_UDID="${DEVICE_UDID:?Set DEVICE_UDID from simctl}"
RESULT_PATH="${RESULT_PATH:-artifacts/CI.xcresult}"

rm -rf "$RESULT_PATH"
mkdir -p "$(dirname "$RESULT_PATH")"

xcodebuild test \
  -workspace "$WORKSPACE" \
  -scheme "$SCHEME" \
  -testPlan CI \
  -destination "platform=iOS Simulator,id=$DEVICE_UDID" \
  -resultBundlePath "$RESULT_PATH"

Speichern Sie unabhängig von Erfolg oder Fehlschlag die .xcresult-Datei, den vollständigen Befehl, die Commit-Kennung, die Xcode-Version und die UDID des ausgewählten Geräts. Bewahren Sie nicht nur die letzten Dutzend Protokollzeilen auf. Nicht ausgeführte Tests, Prozessabstürze und fehlgeschlagene Assertions erfordern unterschiedliche Nachweise. Das Ergebnis-Bundle erhält die Testhierarchie, Anhänge und Diagnoseinformationen.

Beginnen Sie bei der parallelen Ausführung mit konservativen Werten. Test-Targets, die dieselbe Datenbank, einen festen Port oder gemeinsame Dateien verwenden, sollten nicht sofort parallel ausgeführt werden. Isolieren Sie zunächst den Zustand vollständig und aktivieren Sie die Parallelisierung anschließend schrittweise, statt Race Conditions durch Wiederholungsversuche zu kaschieren.

Die Prüfung als Merge-Gate etablieren

Das abschließende Gate sollte immer in derselben Reihenfolge ausgeführt werden: Prüfen, ob das Scheme den Plan findet, die normalisierte Datei erzeugen, sie mit der Baseline vergleichen, nach sensiblen Werten und absoluten Pfaden suchen, die Liste übersprungener Tests kontrollieren und erst danach die Tests starten. So schlagen Konfigurationsfehler bereits vor dem Start des Simulators fehl, was Warte- und Diagnosezeit spart.

Verwenden Sie vor dem Commit folgende Checkliste:

Wenn jede Änderung am XCTestPlan im Code-Review verständlich nachvollzogen werden kann, ist „lokal alles grün, in der Cloud fehlen Tests“ kein sporadisches Rätsel mehr. Stattdessen wird daraus eine Konfigurationsabweichung, die sich bereits vor der Ausführung blockieren lässt.

Häufig gestellte Fragen

Warum genügt ein gemeinsam genutztes Xcode-Scheme nicht?

Das Scheme legt den Einstieg fest, doch XCTestPlan kann Ziele, Konfigurationen, Argumente, Variablen, Sprachen und ausgeschlossene Tests ändern. Die CI muss alle Ebenen festschreiben.

Dürfen Zugriffstoken in XCTestPlan gespeichert werden?

Nein. Im Plan stehen nur Variablennamen oder unkritische Standardwerte. Geheimnisse werden zur Laufzeit aus der kontrollierten CI-Umgebung injiziert und nicht protokolliert.

Kann die Normalisierung wichtige Änderungen verbergen?

Bei einem zu breiten Filter ja. Entfernen Sie nur generierte Kennungen ohne Ausführungsbedeutung und behalten Sie Ziele, Auswahl, Ausschlüsse, Optionen und Konfigurationsnamen bei.

Exklusiver physischer Knoten

Einen dedizierten Cloud-Mac für Ihre Entwicklungs-Pipeline konfigurieren

MangoVM bietet dedizierte physische Knoten mit Apple Silicon in den Varianten M4 und M4 Pro. Wählen Sie Laufzeit, Region und zusätzliche Speicheroptionen, um die vollständigen Bestelldetails zu prüfen.

Konfiguration auswählen und bestellen