Eine lokale Ausführung und ein einzelner Testlauf bestehen, aber die Remote-Mac-CI meldet bei wiederholten Läufen zufällige Fehler? Schalten Sie nicht sofort die gesamte Parallelität ab: Isolieren Sie zuerst gemeinsam genutzte Zustände und Ressourcen, verwenden Sie .serialized nur für den nachweislich betroffenen Bereich und entscheiden Sie erst danach über eine erneute Parallelisierung oder einen getrennten Knoten.

Last updated: 06.09.2026. Die Aussagen zu Parallelisierung, .serialized, XCTest-Koexistenz und Testergebnissen wurden anhand der offiziellen Dokumentation zur parallelen Swift-Testing-Ausführung und der Xcode-Dokumentation zu Testergebnissen geprüft.

Dieser Beitrag ist für drei Rollen gedacht: Swift-Entwickler, die XCTest nach Swift Testing migrieren und nun Reihenfolgefehler sehen; DevOps- oder Testingenieure, die Remote-Mac-Läufe, Ergebnisarchive und Knotenressourcen betreuen; sowie Plattformverantwortliche, die zwischen Refactoring, lokaler Serialisierung und einem zusätzlichen Testknoten entscheiden müssen.

01

Der Fehler wird zuerst als Beweislage behandelt

„Nur in der CI“ ist noch keine Ursache. Ein Fehler kann durch parallele Tests entstehen, aber auch durch einen festen Datenfehler, einen unvollständig beendeten asynchronen Task, einen verschmutzten Arbeitsbereich oder Ressourcenmangel auf dem Knoten.

Swift Testing führt Tests standardmäßig parallel aus. Diese bestätigte Framework-Eigenschaft ist jedoch nicht gleichbedeutend mit „jede zufällige CI-Störung wird durch Swift Testing verursacht“. Die offizielle Beschreibung der parallelen Testausführung ist deshalb der Ausgangspunkt für die Untersuchung, nicht das Ende der Diagnose.

Legen Sie für den ersten Vergleich eine unveränderliche Testbasis fest:

  • derselbe Commit;
  • derselbe Testplan und dasselbe Scheme;
  • derselbe Xcode- und Swift-Testing-Stand;
  • derselbe CI-Aufruf;
  • derselbe Remote-Mac-Arbeitsbereich oder bewusst ein frischer Arbeitsbereich.

Sammeln Sie pro Lauf das Ergebnisbundle, den Namen des fehlgeschlagenen Tests, die beobachtete Reihenfolge, den Start- und Endstatus des Jobs sowie den Zustand des Knotens. Ein einzelner roter Lauf reicht nicht für eine Entscheidung. Ein Fehler, der auch bei alleiniger Ausführung immer erscheint, ist anders zu behandeln als ein Fehler, der nur bei gleichzeitiger Ausführung auftritt.

Drei Parallelitätsebenen dürfen nicht vermischt werden

Innerhalb von Swift Testing können Tests parallel laufen. XCTest kann ebenfalls eigene Ausführungsregeln besitzen. Darüber liegen die CI-Jobs und möglicherweise mehrere Runner, die denselben Remote Mac gleichzeitig verwenden. Diese Ebenen sind technisch und organisatorisch verschieden.

Ein globaler Schalter auf CI-Ebene kann daher einen Konflikt zwischen zwei Jobs nicht lösen, wenn beide weiterhin dasselbe temporäre Verzeichnis oder dieselbe Datenbank verwenden. Umgekehrt kann ein .serialized-Trait innerhalb einer Suite keinen Simulator-Konflikt beheben, wenn mehrere Jobs denselben Simulator oder dieselbe UI-Session beanspruchen.

02

Testautoren beseitigen gemeinsam genutzten Zustand

Der Testautor trägt die Verantwortung für den kleinsten reproduzierbaren Fehler. Beginnen Sie nicht mit einer Suite-weiten Serialisierung, sondern prüfen Sie, ob Tests implizit voneinander abhängen.

Typische Quellen sind globale Variablen, Singleton-Objekte, statische Caches und wiederverwendete Test-Fixtures. Ein Test schreibt einen Wert, ein zweiter Test liest ihn und besteht nur dann, wenn die erwartete Reihenfolge erhalten bleibt. Unter paralleler Ausführung wird daraus ein Wettlauf.

Auch setUp- und tearDown-Ersatzlogik verdient Aufmerksamkeit. Swift Testing verwendet andere Makros und Strukturen als XCTest. Bei einer Migration kann die Initialisierung zwar scheinbar vorhanden sein, aber ein asynchroner Task läuft nach dem eigentlichen Testende weiter. Dann verändert er später den Zustand eines anderen Tests.

Gehen Sie in dieser Reihenfolge vor:

  1. Entfernen Sie globale Testdaten, sofern sie nicht ausdrücklich Teil des Tests sind.
  2. Erzeugen Sie Fixtures pro Test und nicht einmal pro Prozess.
  3. Warten Sie auf das Ende asynchroner Tasks, bevor der Test als abgeschlossen gilt.
  4. Setzen Sie UserDefaults, Benachrichtigungsbeobachter und Caches vollständig zurück.
  5. Wiederholen Sie den Lauf mit veränderter Reihenfolge und anschließend mit alleiniger Ausführung.

Die Apple-Anleitung zur Migration von XCTest hilft bei der Zuordnung der Framework-Konzepte. Sie ersetzt aber nicht die Prüfung Ihrer eigenen Zustandsgrenzen.

Übergabe an die CI-Rolle: Der Testautor sollte nicht nur „behoben“ melden. Übergeben Sie den betroffenen Zustand, den reproduzierbaren Testbefehl, das Ergebnisbundle vor und nach der Änderung sowie die Bedingung, unter der Parallelität wieder aktiviert werden darf.

Stop-Bedingung: Wenn der Fehler nach isolierter Fixture-Erzeugung, sauberem Aufräumen und alleiniger Wiederholung unverändert bleibt, stoppen Sie das Refactoring. Die nächste Prüfung gehört dem Arbeitsbereich, der Ressource oder dem Knoten.

03

Anwendungsteams isolieren Dateien, Ports und Systemdienste

Viele vermeintliche Framework-Fehler sind Namenskonflikte. Ein fester Pfad wie /tmp/test.sqlite, ein hart codierter Netzwerkport oder ein gemeinsamer Schlüsselbund-Eintrag kann zwei ansonsten korrekte Tests miteinander verbinden.

Prüfen Sie mindestens diese Ressourcen:

  • temporäre Verzeichnisse und Dateien;
  • Datenbankdateien und Lock-Dateien;
  • lokale Netzwerkports;
  • UserDefaults-Suite-Namen;
  • Keychain-Accounts und Zugriffsschlüssel;
  • NotificationCenter-Beobachter;
  • Simulatoren, UI-Sessions und gestartete Hilfsprozesse.

Erzeugen Sie für jeden Test oder jede Testgruppe eine eindeutige Namespace-Kennung. Der Test muss diese Kennung an Dateinamen, Datenbankpfade und Ports weitergeben. Bei Ports sollte der Test, sofern die Anwendung dies erlaubt, einen vom Betriebssystem zugewiesenen freien Port nutzen. Bei Keychain-Daten ist die Isolation besonders kritisch: Das Löschen eines Eintrags kann einen anderen Test oder eine lokale Entwicklungsumgebung beschädigen.

Das gilt auch für Bereinigungsskripte. Ein pauschales Löschen von DerivedData oder Keychain-Inhalten kann einen grünen Lauf erzeugen, ohne die Ursache zu beseitigen. Dokumentieren Sie deshalb vor jeder Änderung, welche Daten entfernt werden, wer sie verwendet und wie die Änderung zurückgerollt wird.

Prozessinterne und externe Parallelität getrennt bewerten

Ein Prozess kann seine Tests parallel ausführen, während der CI-Runner gleichzeitig mehrere Prozesse startet. Simulator- oder UI-Tests bringen zusätzliche Exklusivität mit. Eine einzige globale Parallelitätsoption beschreibt diese Situation nicht ausreichend.

Wenn nur UI-nahe Tests scheitern, während reine Einheiten-Tests stabil bleiben, ist das ein Hinweis auf eine andere Isolationsgrenze. Beweisen Sie dies durch getrennte Testziele oder Testgruppen. Die Apple-Dokumentation zur Organisation von Tests in Xcode beschreibt, wie Testgruppen und Testpläne für solche Vergleiche genutzt werden können.

04

Migrationsteams prüfen XCTest, Test Plan und Aufrufpfad

Bei einer Migration existieren häufig alte XCTest-Ziele und neue Swift-Testing-Suites nebeneinander. Das ist offiziell möglich: Die Migrationsdokumentation beschreibt die gemeinsame Verwendung. Problematisch wird die Diagnose, wenn niemand mehr genau weiß, welcher Test über welches Target und welchen Plan gestartet wurde.

Prüfen Sie je Test:

  • Gehört er zu einem XCTest-Target oder zu einem Swift-Testing-Target?
  • Startet das Scheme beide Gruppen?
  • Verwendet die CI denselben Test Plan wie Xcode lokal?
  • Werden Tests über eine einzelne Destination oder mehrere Destinations ausgeführt?
  • Erzeugt jeder Job ein eigenes Ergebnisbundle?
  • Wird ein alter Filter oder ein veraltetes Kommando weiterverwendet?

Die Xcode-Dokumentation zum Hinzufügen von Tests ist für die Target-Zuordnung relevant. Für die Auswertung sollten Sie das Ergebnisbundle nicht durch eine verkürzte Logzeile ersetzen. Die Reihenfolge, der konkrete Fehler und die Testgruppe müssen nach dem Lauf nachvollziehbar bleiben.

Stop-Bedingung für die Migration: Wenn ein Test lokal und in der CI nicht eindeutig demselben Target zugeordnet werden kann, ändern Sie noch keine Parallelitätsregel. Erst die Ausführung vereinheitlichen, dann den Fehler erneut erfassen.

05

.serialized bleibt eine begrenzte Schutzmaßnahme

.serialized ist kein allgemeiner Reparaturknopf. Die offizielle Beschreibung des ParallelizationTrait bestätigt die Serialisierung für eine Suite beziehungsweise für den relevanten parametrisierten Testbereich. Die Dokumentation zu parametrisierten Tests ist maßgeblich, wenn mehrere Eingabefälle beteiligt sind.

Setzen Sie den Trait nur dort ein, wo ein gemeinsamer Zustand nachgewiesen ist und eine sofortige Entkopplung nicht realistisch ist. Der Eintrag muss zusammen mit einer Begründung versioniert werden:

  • Welche Datei, welcher Port oder welcher Dienst ist nicht isoliert?
  • Warum kann der Test kurzfristig nicht umgebaut werden?
  • Welche anderen Tests bleiben parallel?
  • Welche Messung entscheidet über die Entfernung?
  • Wer prüft die Einschränkung nach dem nächsten Refactoring?

Vermeiden Sie eine globale Serialisierung aller Suites. Sie verlängert Rückmeldungen, verdeckt Abhängigkeiten und kann die eigentliche Konkurrenz mehrerer CI-Jobs unberührt lassen. Bei parametrisierten Tests müssen Sie zusätzlich prüfen, ob der Konflikt zwischen einzelnen Eingabefällen oder zwischen der gesamten Suite entsteht.

06

CI- und DevOps-Teams beweisen die Umgebung

Ein Remote Mac ist nicht nur ein Testfenster. Während des Testlaufs können andere Jobs, Hintergrundprozesse, große Build-Artefakte oder ein fast volles Dateisystem die Ergebnisse beeinflussen. Das ist besonders relevant, wenn mehrere Runner denselben Knoten nutzen.

Prüfen Sie vor dem Vergleich:

  1. Erstellen Sie einen frischen Klon des festen Commits.
  2. Verwenden Sie eine eigene DerivedData für den Testlauf.
  3. Geben Sie jedem Job ein eigenes temporäres Verzeichnis.
  4. Erfassen Sie Speicher- und Festplattenzustand sowie aktive CI-Prozesse.
  5. Speichern Sie Ergebnisbundle und Knotenprotokoll gemeinsam.
  6. Wiederholen Sie den Lauf parallel, allein und nach einem Neustart des Knotens.

Die Reihenfolge ist wichtig. Ein Lauf aus einem verschmutzten Arbeitsbereich kann einen Codefehler vortäuschen. Ein Lauf auf einem stark belasteten Knoten kann einen Ressourcenfehler verbergen, wenn er später allein wiederholt wird.

Für die Arbeitsbereich-Isolation kann eine Anleitung zur Xcode-Testknoten-Isolation als ergänzende Betriebsplanung dienen. Wenn Sie für die Untersuchung einen getrennten Mac-Knoten benötigen, sollten Sie die Mietkosten für Mac-Mini-Testumgebungen erst nach der technischen Abgrenzung vergleichen. Die Hardwarewahl ist kein Ersatz für reproduzierbare Testdaten.

07

FAQ für die Fehleranalyse

Warum schlagen Swift-Testing-Tests nur in der CI gelegentlich fehl?

In der CI treffen parallele Testausführung, gemeinsam genutzte Dateien, Ports, UserDefaults, Keychain-Einträge und Hintergrundaufgaben aufeinander. Zusätzlich können mehrere Jobs denselben Remote-Mac-Knoten belasten. Prüfen Sie deshalb zuerst Wiederholbarkeit, Ausführungsreihenfolge, Arbeitsbereich und Knotenstatus, bevor Sie einen Fehler dem Framework zuschreiben.

Wie lässt sich die parallele Ausführung nur für einen Teil der Tests abschalten?

Verwenden Sie die von Swift Testing bereitgestellte Serialisierungs-Eigenschaft nur für die Suite oder den parametrisierten Testbereich, der nachweislich einen gemeinsamen Zustand benötigt. Lassen Sie unabhängige Suites parallel laufen. Eine globale Abschaltung verdeckt häufig Isolationsfehler und sollte höchstens als dokumentierter Rückfall während der Untersuchung dienen.

Gehört .serialized an eine Testfunktion oder an eine Suite?

Die offizielle Semantik unterstützt eine begrenzte Serialisierung auf Suite-Ebene sowie für parametrisierte Tests. Entscheidend ist nicht die mechanische Platzierung, sondern der kleinste Bereich, der tatsächlich einen gemeinsamen Zustand schützt. Dokumentieren Sie den betroffenen Zustand, den Grund für die Einschränkung und die Bedingung, unter der sie wieder entfernt wird.

Beeinflusst die gemeinsame Nutzung von Swift Testing und XCTest die Parallelität?

Swift Testing und XCTest können im selben Projekt koexistieren. Daraus folgt jedoch nicht automatisch, dass beide Frameworks dieselben Ressourcen unabhängig verwenden. Test Plan, Scheme, Zielzuordnung und CI-Aufruf können unterschiedliche Mengen von Tests starten. Erfassen Sie daher Framework, Target und Ausführungsparameter getrennt, bevor Sie Parallelitätsregeln ändern.

Wie lässt sich ein Parallelitätsfehler auf einem Remote Mac reproduzieren?

Fixieren Sie Commit, Toolchain, Testbefehl und Testplan. Wiederholen Sie denselben Lauf unter parallelen Bedingungen, führen Sie den gemeldeten Test anschließend allein aus und wiederholen Sie ihn in einem frischen Klon mit eigener DerivedData und temporären Verzeichnissen. Speichern Sie Ergebnisbundle, Reihenfolge, Fehlertext und Knotenzustand gemeinsam.

08

Die Entscheidung fällt nach Beweis, nicht nach Bauchgefühl

Nutzen Sie nach der Untersuchung diese Abgrenzung. Sie beschreibt keine garantierte Stabilitätssteigerung, sondern die passende nächste Maßnahme für den jeweils belegten Zustand.

Befund Primäre Maßnahme Parallelität Übergabe und Rückkehrbedingung
Gemeinsamer Zustand im Test ist reproduzierbar Fixture, Cache und Bereinigung refaktorieren Beibehalten oder schrittweise wiederherstellen Testautor liefert Vorher-Nachher-Ergebnisse; Trait erst nach stabiler Wiederholung entfernen
Einzelne Datei, Port- oder Keychain-Ressource ist nicht isolierbar Kleinsten betroffenen Bereich mit .serialized schützen Nur diesen Bereich serialisieren Anwendungsteam dokumentiert Ressource und Entfernungskriterium
Mehrere Jobs verwenden denselben Arbeitsbereich Klon, DerivedData und temporäre Pfade trennen Job-Konflikt beseitigen DevOps prüft parallele Jobs erneut; kein globales Framework-Flag als Ersatz
Fehler hängt mit Simulator oder UI-Prozess zusammen Testgruppe oder Destination isolieren Prozessinterne und externe Parallelität getrennt steuern CI-Team archiviert getrennte Ergebnisbundles
Fehler bleibt im frischen Klon allein bestehen Code-, Toolchain- oder Testdatenfehler untersuchen Nicht durch Serialisierung kaschieren Testautor und Migrationsteam übernehmen gemeinsam
Ursache ist noch nicht nachgewiesen Zeitlich begrenzter globaler Rückfall Nur als Diagnosemaßnahme Ablaufdatum und Wiederaufnahme der Parallelität festlegen

Der globale Rückfall ist nur dann vertretbar, wenn er sichtbar dokumentiert wird. Notieren Sie den betroffenen Commit, die beobachtete Fehlerrate nicht als unbelegte Zahl, die Startzeit der Maßnahme und das konkrete Kriterium für die Rückkehr zur parallelen Ausführung. Ohne diese Angaben wird aus einem Diagnosewerkzeug schnell eine dauerhafte Verschlechterung der CI-Rückmeldung.

09

Ein Remote-Mac-Knoten ist nur bei einer klaren Betriebsgrenze sinnvoll

Wenn Ihr aktueller Rechner den Fehler nicht unter kontrollierten Bedingungen reproduziert, kann ein unabhängiger Remote Mac die Untersuchung vereinfachen. Entscheidend ist nicht der Standort, sondern die Trennung: gleicher Commit, gleicher Testplan, eigener Arbeitsbereich und nachvollziehbare Ergebnisarchive. Sie vergleichen dann parallele Ausführung, lokale .serialized-Einschränkung und saubere Umgebung, ohne den Entwicklungsrechner zu verändern.

Die vorhandene Lösung hat jedoch reale Nachteile, wenn sie auf einem gemeinsam genutzten Laptop oder einer allgemeinen Linux-Cloud basiert: macOS-spezifische Testwerkzeuge fehlen, Hintergrundprozesse verschmutzen den Zustand und mehrere Jobs konkurrieren häufig um dieselben Pfade. Eine virtuelle oder nicht unterstützte macOS-Umgebung kann zusätzlich bei Simulator, Signierung und Systemdiensten vom späteren Produktionsknoten abweichen.

Für eine zeitlich begrenzte Reproduktion oder einen getrennten CI-Testknoten kann VpsMesh deshalb praktischer sein als der Kauf eines zusätzlichen Mac. Das ist nicht automatisch die beste Lösung für dauerhaft hohe Last, spezielle physische Schnittstellen oder eine Umgebung, die Sie über lange Zeit selbst besitzen und vollständig kontrollieren müssen. Für eine reproduzierbare Untersuchung mit anschließendem Rückbau ist Mieten jedoch oft der sauberere Versuch: Sie ändern nicht den Arbeitsplatz und behalten die Entscheidung zwischen Test-Refactoring und Infrastrukturmaßnahme offen.

Die Leitlinie für instabile parallele Swift-Testing-Tests lautet daher: erst Beweise sammeln, dann Zustände und Ressourcen isolieren, anschließend nur den belegten Bereich mit .serialized schützen und erst nach sauberen Wiederholungsläufen über die Rückkehr zur Parallelität entscheiden.