Damit Xcode den Test hervorhebt, der eine gemeinsame XCTest-Hilfsfunktion aufgerufen hat, statte die Hilfsfunktion mit den Standardparametern #filePath und #line aus und reiche beide an ihre Assertions weiter. Diese Anleitung zeigt die Lösung, verschachtelte Hilfsfunktionen und das Swift-Testing-Gegenstück.
Warum hebt Xcode die Hilfsfunktion hervor?
Eine gemeinsame Assertion führt einen weiteren Quellcodeort ein. Der Test ruft deine Hilfsfunktion auf, und die Hilfsfunktion ruft eine XCTest-Assertion auf. Verwendet diese Assertion ihre Standardargumente für den Ort, wird als gemeldeter Ort die Assertion innerhalb der Hilfsfunktion angegeben. Apple dokumentiert file: StaticString = #filePath und line: UInt = #line sowohl für XCTAssertEqual als auch für XCTFail.
Erfasse den Ort des Aufrufers an der Schnittstelle der Hilfsfunktion und gib diese Werte anschließend weiter. Die Standardwerte für Quellcodeorte in Swift erfassen den Aufrufort; das Swift-Projekt erläutert dieses Verhalten in SE-0274: Prägnante magische Dateinamen. Apple zeigt dasselbe XCTest-Hilfsfunktionsmuster auch in Zu Swift Testing migrieren und demonstriert dabei, wie Xcode den Fehler dem Aufruf der Hilfsfunktion zuordnet.
Für Entwickler, die mit Xcode auf einem Mac arbeiten, besteht die konkrete Aufgabe darin, wiederverwendbare Prüfungen beizubehalten und zugleich sicherzustellen, dass jeder Fehler zum relevanten Testeingabewert zurückführt. Die folgenden Beispiele verwenden ausschließlich kleine Ganzzahlarrays. Beim Ausführen benötigen sie weder ein App-Modell noch einen Dienstersatz, heruntergeladene Abhängigkeiten oder Netzwerkzugriff.
Aufrufer-Ortsparameter zu einer XCTest-Hilfsfunktion hinzufügen
Verwende ein vorhandenes macOS-Unit-Testziel. Falls das Projekt eines benötigt, wähle File > New > Target, filtere nach Test und wähle Unit Testing Bundle. Um eine Testdatei hinzuzufügen, wähle File > New > New File From Template und anschließend XCTest Unit Test. Apple dokumentiert diese Pfade unter Tests zum Xcode-Projekt hinzufügen.
Lege diese vollständige Testdatei in diesem Unit-Testziel ab. Der zweite Test gibt absichtlich eine falsche erwartete Summe vor, damit du den Fehlerort prüfen kannst.
import XCTest
private func assertTotal(
_ values: [Int],
equals expected: Int,
file: StaticString = #filePath,
line: UInt = #line
) {
let actual = values.reduce(0, +)
XCTAssertEqual(
actual,
expected,
"Unexpected total for \(values)",
file: file,
line: line
)
}
final class TotalHelperTests: XCTestCase {
func testMatchingTotal() {
assertTotal([2, 3, 4], equals: 9)
}
func testDeliberatelyIncorrectTotal() {
assertTotal([2, 3, 4], equals: 10)
}
}
Entscheidend sind die Parametertypen, die Standardwerte und das explizite Weiterreichen. StaticString und UInt entsprechen der Signatur der XCTest-Assertion. Belasse #filePath und #line direkt in den Standardwerten der Hilfsfunktion. Der Test ruft die Hilfsfunktion dann auf, ohne einen der beiden Ortsparameter manuell anzugeben. Siehe die dokumentierten XCTAssertEqual-Parameter.
Die Rechnung dient der Veranschaulichung: 2 + 3 + 4 ergibt 9; daher stimmt der erste Vergleich, der zweite jedoch nicht. Diese Rechenbeispiele wurden lokal mit Python überprüft. In der Forschungsumgebung war keine Swift-Laufzeit verfügbar, deshalb wurden die Swift-Beispiele geprüft, hier aber nicht kompiliert oder ausgeführt.
Ort und Testergebnis überprüfen
Wähle Product > Test oder führe den einzelnen Test über die Wiedergabesteuerung neben seiner Deklaration aus. Wähle danach den fehlgeschlagenen Test im Test navigator aus und prüfe die Diagnose. Apple beschreibt diese Steuerelemente und die Fehlerdetails unter Tests ausführen und Ergebnisse interpretieren.
Prüfe bei diesem Beispiel zwei getrennte Ergebnisse: testDeliberatelyIncorrectTotal() schlägt fehl, und seine Assertion-Diagnose verweist auf den Aufruf assertTotal([2, 3, 4], equals: 10). Die erwartete Zuordnung zum Aufrufer folgt dem von Apple gezeigten Weitergabemuster. Ändere nach der Prüfung 10 zu 9 und führe die Tests erneut aus; die absichtliche Abweichung sollte aus der fertigen Testsuite entfernt werden.
Wenn die Diagnose weiterhin auf die Hilfsfunktion verweist, prüfe den letzten Assertion-Aufruf. Ortsparameter zu deklarieren reicht nicht aus, wenn die Hilfsfunktion beim Erfassen des Fehlers file: file oder line: line nicht angibt.
Den Ort durch alle Ebenen von Hilfsfunktionen weiterreichen
Auch verschachtelte Hilfsfunktionen benötigen dieselbe explizite Weitergabe. Angenommen, ein Test ruft eine domänenspezifische Hilfsfunktion auf, die wiederum eine Assertion-Hilfsfunktion auf niedrigerer Ebene aufruft. Lässt die äußere Hilfsfunktion die Ortsargumente aus, erfasst die untergeordnete Hilfsfunktion den dazwischenliegenden Aufrufort.
Hier gilt es eine Sprachgrenze zu beachten: Standardwerte für Quellcodeorte werden nicht automatisch durch beliebige Hilfsfunktionsaufrufe weitergereicht. SE-0285: Den Übergang zu prägnanten magischen Dateizeichenfolgen erleichtern behandelt ausdrücklich die nichttransitive Wirkung dieser Standardwerte.
Die folgende vollständige alternative Testdatei zeigt, wie eine Hilfsfunktion eine andere aufruft und dabei den ursprünglichen Testort beibehält.
import XCTest
private func assertIntegerEqual(
_ actual: Int,
_ expected: Int,
file: StaticString = #filePath,
line: UInt = #line
) {
XCTAssertEqual(actual, expected, file: file, line: line)
}
private func assertRowTotal(
_ row: [Int],
equals expected: Int,
file: StaticString = #filePath,
line: UInt = #line
) {
assertIntegerEqual(
row.reduce(0, +),
expected,
file: file,
line: line
)
}
final class NestedTotalHelperTests: XCTestCase {
func testRowTotal() {
assertRowTotal([2, 3, 4], equals: 9)
}
}
Nutze beim Prüfen einer längeren Kette von Hilfsfunktionen eine einfache Nachverfolgung: Beginne beim Testaufruf, folge jeder Hilfsfunktion und prüfe, ob derselbe erfasste Ort die Assertion erreicht. Erfasse Standardwerte an der Schnittstelle, die im Ergebnis erscheinen soll, und reiche vorhandene Werte durch die übrigen Ebenen weiter. Vermeide es, die Erfassung hinter einer weiteren Funktion zu verbergen, die als Standardargument verwendet wird – die von SE-0285 veranschaulichte Fehlerquelle.
Beendet das Melden eines Fehlers den aufrufenden Test?
Fehlerzuordnung und Kontrollfluss sind getrennte Entscheidungen. XCTest verwendet für continueAfterFailure standardmäßig true, sodass die Ausführung nach einer fehlgeschlagenen Assertion normalerweise fortgesetzt wird. Eine Änderung der gemeldeten Datei und Zeile ändert diese Eigenschaft nicht. Apple dokumentiert dieses Verhalten unter continueAfterFailure.
Wenn eine Hilfsfunktion eine Bedingung feststellt, durch die ihre restliche Arbeit ungültig wird, gib ihr einen expliziten Ausstiegspfad. Melde zum Beispiel den Fehler mit dem weitergereichten Ort und kehre anschließend aus der Hilfsfunktion zurück. Denk daran: Die Rückkehr aus einer Hilfsfunktion gibt die Kontrolle an ihren Aufrufer zurück. Plane die weiteren Schritte des Aufrufers entsprechend. Apples Migrationsleitfaden zeigt einen bedingungslosen Fehleraufruf mit anschließender Rückgabe.
Halte die erste Überprüfung synchron und klein. Stelle sicher, dass eine absichtlich falsche Berechnung am erwarteten Aufrufort fehlschlägt, bevor du aufwendigere Einrichtung oder asynchrones Verhalten hinzufügst. So lässt sich ein Fehler bei der Weitergabe des Orts von anderen Problemen bei der Testausführung unterscheiden.
Einen unterstützten Quellcodeort in Swift Testing verwenden
Verwende für eine von Swift-Testing-Tests aufgerufene Hilfsfunktion #expect mit einem expliziten SourceLocation. Apple dokumentiert sourceLocation als den Ort, dem Erwartungen und Probleme zugeordnet werden, und erklärt, dass eine falsche Bedingung ein Problem für den Test erfasst, der in der aktuellen Aufgabe ausgeführt wird. Siehe expect(_:_:sourceLocation:).
Diese vollständige alternative Datei erfordert Swift Testing, verfügbar mit Xcode 16 und Swift 6.0. Sie erfasst die vier Ortskomponenten jeweils als eigenen Standardwert und erstellt anschließend den dokumentierten SourceLocation-Initialisierer.
import Testing
private func expectTotal(
_ values: [Int],
equals expected: Int,
fileID: String = #fileID,
filePath: String = #filePath,
line: Int = #line,
column: Int = #column
) {
let location = SourceLocation(
fileID: fileID,
filePath: filePath,
line: line,
column: column
)
let actual = values.reduce(0, +)
#expect(actual == expected, sourceLocation: location)
}
@Test func matchingTotal() {
expectTotal([2, 3, 4], equals: 9)
}
@Test func deliberatelyIncorrectTotal() {
expectTotal([2, 3, 4], equals: 10)
}
Der Initialisierer erfordert eine korrekt formatierte, nicht leere Datei-ID sowie positive Zeilen- und Spaltennummern. Durch die Erfassung der vom Compiler bereitgestellten Komponenten musst du diese Werte nicht selbst erfinden. Wenn du solche Hilfsfunktionen verschachtelst, reiche alle vier erfassten Argumente weiter – genauso wie bei der XCTest-Version mit ihren beiden Argumenten. Korrigiere auch hier nach der Prüfung der Zuordnung die absichtlich falsche Erwartung 10.
Was ändert sich, wenn XCTest und Swift Testing eine Hilfsfunktion gemeinsam verwenden?
Beide Frameworks können in einem Test-Bundle koexistieren, doch eine Hilfsfunktion, die Framework-Grenzen überschreitet, erfordert eine versionsabhängige Behandlung. Apples aktueller Migrationsleitfaden dokumentiert die Interoperabilität und ihre Standardwerte: Toolchains vor Swift 6.4 verwenden none; Swift 6.4 oder neuer verwendet standardmäßig limited für Pakete mit einer älteren Tools-Version und complete für Pakete mit Tools-Version 6.4 oder neuer.
| Interoperabilitätsmodus | XCTest-Assertion schlägt innerhalb eines Swift-Testing-Tests fehl |
|---|---|
none |
Frameworkübergreifendes Problem wird ignoriert |
limited |
Wird als Warnung mit Hinweisen zur Modernisierung gemeldet |
complete |
Behält den Fehler-Schweregrad bei und enthält Hinweise zur Modernisierung |
strict |
Wird mit fatalError gemeldet |
Diese Modi erklären, warum eine Hilfsfunktion den richtigen Text melden kann, während ein Swift-Testing-Test dennoch besteht. Apples WWDC26-Migrationssession zeigt genau dieses Ergebnis und ändert anschließend die Interoperabilitätseinstellung des Testplans unter Test Execution zu Complete, damit der Fehler-Schweregrad erhalten bleibt. Prüfe deine installierte Toolchain, bevor du dich auf diese Funktion verlässt.
Verwende bei älteren Toolchains für jedes Framework die jeweils eigene Methode zur Meldung von Assertions und teile darunter die deterministische Berechnung. Für unterstützte Interoperabilitätskonfigurationen zeigt Apple außerdem, wie sich XCTFail in einer Hilfsfunktion durch Issue.record aus Swift Testing ersetzen lässt. Bei dieser Migration muss die Weitergabe des Quellcodeorts ebenfalls erhalten bleiben.
Das verbleibende Symptom diagnostizieren
| Beobachtung | Was als Nächstes zu prüfen ist |
|---|---|
| Fehler verweist auf die Assertion-Hilfsfunktion | Prüfen, ob die Assertion die erfassten Ortsargumente erhält |
| Fehler verweist auf eine äußere Hilfsfunktion | Prüfen, ob diese äußere Hilfsfunktion den Ort ihres Aufrufers weiterreicht |
| Swift-Testing-Test besteht trotz einer XCTest-Assertion | Unterstützung der Toolchain und Interoperabilitätsmodus prüfen |
| Code wird nach einer fehlgeschlagenen XCTest-Assertion ausgeführt | Gewünschten Kontrollfluss und continueAfterFailure prüfen |
| Im Testlauf erscheint kein Beispieltest | Prüfen, ob die Datei zum Unit-Testziel gehört und der aktive Testplan sie einschließt |
Apples Anleitung zur Testeinrichtung und Anleitung zur Testausführung beschreiben Testziele und aktive Testpläne sowie die Erkennung und Auswahl von Tests. Verwende bei Framework-übergreifenden Tests zunächst die oben dokumentierten Interoperabilitätsregeln, bevor du Ortsargumente änderst.
Eine nützliche gemeinsame Hilfsfunktion bewahrt drei Dinge: einen aussagekräftigen Vergleich, eine Diagnose, die dem vorgesehenen Aufrufer zugeordnet ist, und das gewünschte Testergebnis. Prüfe dies mit einer absichtlichen Abweichung, entferne sie anschließend und reiche den erfassten Ort bei jeder zusätzlichen Ebene von Hilfsfunktionen weiter.
Quellen
- XCTAssertEqual(::_:file:line:) — Apple
- XCTFail(_:file:line:) — Apple
- Tests zum Xcode-Projekt hinzufügen — Apple
- Tests ausführen und Ergebnisse interpretieren — Apple
- continueAfterFailure — Apple
- Einen Test von XCTest migrieren — Apple
- expect(::sourceLocation:) — Apple
- init(fileID:filePath:line:column:) — Apple
- Zu Swift Testing migrieren — Apple
- Prägnante magische Dateinamen — Swift-Projekt
- Den Übergang zu prägnanten magischen Dateizeichenfolgen erleichtern — Swift-Projekt