Per far sì che Xcode evidenzi il test che ha chiamato un helper XCTest condiviso, dai all'helper parametri predefiniti #filePath e #line e inoltra entrambi alle sue asserzioni. Questa procedura mostra la correzione, gli helper annidati e l'equivalente in Swift Testing.

Perché Xcode evidenzia l'helper?

Un'asserzione condivisa introduce un'altra posizione nel codice sorgente. Il test chiama il tuo helper e l'helper chiama un'asserzione XCTest. Se quell'asserzione usa i suoi argomenti di posizione predefiniti, la posizione segnalata è l'asserzione all'interno dell'helper. Apple documenta file: StaticString = #filePath e line: UInt = #line sia su XCTAssertEqual che su XCTFail.

Cattura la posizione del chiamante al confine dell'helper, quindi passa quei valori avanti. I valori predefiniti per la posizione nel codice sorgente di Swift catturano il sito di chiamata; il progetto Swift spiega questo comportamento in SE-0274: Concise magic file names. Apple dimostra anche questo esatto pattern di helper XCTest in Migrate to Swift Testing, mostrando Xcode che attribuisce il fallimento alla chiamata dell'helper.

Per uno sviluppatore che lavora in Xcode su Mac, l'attività concreta è preservare controlli riutilizzabili facendo in modo che ogni fallimento rimandi all'input di test pertinente. Gli esempi seguenti usano solo piccoli array di interi. Non richiedono modello di app, sostituto di servizio, dipendenza scaricata o accesso alla rete quando vengono eseguiti.

Aggiungi parametri di posizione del chiamante a un helper XCTest

Usa un target di test unitari macOS esistente. Se il progetto ne ha bisogno, scegli File > Nuovo > Target, filtra per Test e seleziona Unit Testing Bundle. Per aggiungere un file di test, scegli File > Nuovo > Nuovo file da modello e seleziona XCTest Unit Test. Questi sono i percorsi documentati da Apple in Adding tests to your Xcode project.

Posiziona questo file di test completo in quel target di test unitari. Il secondo test fornisce deliberatamente un totale atteso errato in modo che tu possa ispezionare la posizione del fallimento.

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)
    }
}

Gli elementi importanti sono i tipi di parametro, i valori predefiniti e l'inoltro esplicito. StaticString e UInt corrispondono alla firma delle asserzioni XCTest. Mantieni #filePath e #line direttamente nei valori predefiniti dell'helper. Il test chiama quindi l'helper senza fornire manualmente alcun argomento di posizione. Vedi i XCTAssertEqual parameters documentati.

L'aritmetica è illustrativa: 2 + 3 + 4 è 9, quindi il primo confronto corrisponde e il secondo no. Questi casi aritmetici sono stati verificati localmente con Python. Un eseguibile Swift non era disponibile nell'ambiente di ricerca, quindi gli esempi Swift sono stati ispezionati ma non compilati o eseguiti qui.

Verifica la posizione e il risultato del test

Scegli Prodotto > Test, oppure esegui il singolo test usando il controllo di riproduzione accanto alla sua dichiarazione. Dopodiché, seleziona il test fallito nel Navigatore test e ispeziona la diagnostica. Apple descrive questi controlli e i dettagli del fallimento in Running tests and interpreting results.

Per questo esempio, verifica due risultati separati: testDeliberatelyIncorrectTotal() fallisce e la sua diagnostica di asserzione punta alla chiamata assertTotal([2, 3, 4], equals: 10). L'attribuzione al chiamante attesa segue il pattern di inoltro dimostrato da Apple. Dopo averlo controllato, cambia 10 in 9 ed esegui di nuovo i test; l'errore intenzionale dovrebbe essere rimosso dalla suite di test finale.

Se la diagnostica punta ancora all'interno dell'helper, ispeziona la chiamata di asserzione finale. Dichiarare parametri di posizione è insufficiente quando l'helper omette file: file o line: line nel punto che registra il fallimento.

Preserva la posizione attraverso ogni livello di helper

Gli helper annidati necessitano dello stesso inoltro esplicito. Supponi che un test chiami un helper di dominio, che a sua volta chiami un helper di asserzione di livello inferiore. Se l'helper esterno omette gli argomenti di posizione, l'helper di livello inferiore cattura quel sito di chiamata intermedio.

Questo è un confine linguistico che vale la pena controllare: i valori predefiniti per la posizione nel codice sorgente non viaggiano automaticamente attraverso chiamate di helper arbitrarie. SE-0285: Ease the transition to concise magic file strings discute esplicitamente il comportamento non transitivo di questi valori predefiniti.

Il seguente è un file di test alternativo completo. Dimostra un helper che ne chiama un altro preservando la posizione del test originale.

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)
    }
}

Usa un semplice esercizio di tracciamento quando rivedi una catena di helper più grande: inizia dalla chiamata del test, segui ogni helper e verifica che la stessa posizione catturata raggiunga l'asserzione. Cattura i valori predefiniti al confine destinato ad apparire nel risultato; inoltra i valori esistenti attraverso i livelli rimanenti. Evita di nascondere la cattura dietro un'altra funzione usata come argomento predefinito, l'insidia illustrata da SE-0285.

La segnalazione di un fallimento arresta il test chiamante?

L'attribuzione del fallimento e il flusso di controllo sono decisioni separate. continueAfterFailure di XCTest ha come valore predefinito true, quindi un'asserzione fallita normalmente permette all'esecuzione di continuare. Cambiare il file e la riga segnalati non cambia quella proprietà. Apple documenta questo comportamento in continueAfterFailure.

Se un helper rileva una condizione che rende non valido il suo lavoro rimanente, dai a quell'helper un percorso di uscita esplicito. Ad esempio, registra il fallimento con la posizione inoltrata e poi esci dall'helper. Ricorda che uscire da un helper restituisce il controllo al suo chiamante; progetta il lavoro successivo del chiamante di conseguenza. La migration guide di Apple illustra un fallimento incondizionato seguito da un ritorno.

Mantieni la prima verifica sincrona e piccola. Stabilisci che un calcolo intenzionalmente errato fallisca nel sito di chiamata atteso prima di aggiungere configurazioni più elaborate o comportamenti asincroni. Quella sequenza separa un difetto di inoltro della posizione da altri problemi di esecuzione dei test.

Usa una posizione di origine supportata in Swift Testing

Per un helper chiamato dai test Swift Testing, usa #expect con un SourceLocation esplicito. Apple documenta sourceLocation come la posizione a cui vengono attribuite aspettative e problemi, e afferma che una condizione falsa registra un problema per il test in esecuzione nell'attività corrente. Vedi expect(_:_:sourceLocation:).

Questo file alternativo completo richiede Swift Testing, disponibile con Xcode 16 e Swift 6.0. Cattura i quattro componenti della posizione come valori predefiniti separati, quindi costruisce il SourceLocation initializer documentato.

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)
}

L'inizializzatore richiede un ID file correttamente formattato e non vuoto e numeri di riga e colonna positivi. Catturare i componenti forniti dal compilatore evita di inventare quei valori. Quando annidi questi helper, inoltra tutti e quattro gli argomenti catturati, proprio come la versione XCTest inoltra i suoi due argomenti. Di nuovo, correggi l'aspettativa 10 deliberata dopo aver verificato l'attribuzione.

Cosa cambia quando XCTest e Swift Testing condividono un helper?

Entrambi i framework possono coesistere in un unico bundle di test, ma un helper che attraversa i confini del framework richiede una gestione consapevole della versione. L'attuale migration guide di Apple documenta l'interoperabilità e i suoi valori predefiniti: le toolchain precedenti a Swift 6.4 usano none; Swift 6.4 o versioni successive ha come valore predefinito limited per i pacchetti che dichiarano una versione degli strumenti precedente e complete per i pacchetti che dichiarano la versione degli strumenti 6.4 o successiva.

Modalità di interoperabilità Fallimento asserzione XCTest all'interno di un test Swift Testing
none Problema cross-libreria ignorato
limited Segnalato come avviso, con indicazioni per la modernizzazione
complete Mantiene la gravità del fallimento, con indicazioni per la modernizzazione
strict Segnalato usando fatalError

Queste modalità spiegano perché un helper può segnalare il testo corretto ma lasciare un test Swift Testing che passa. La WWDC26 migration session di Apple mostra esattamente questo risultato, poi cambia l'impostazione di interoperabilità del piano di test sotto Test Execution in Complete per preservare la gravità del fallimento. Controlla la toolchain installata prima di fare affidamento su quella funzionalità.

Per toolchain più vecchie, mantieni la segnalazione delle asserzioni nativa per ogni framework e condividi il calcolo deterministico sottostante. Per configurazioni di interoperabilità supportate, Apple dimostra anche la sostituzione di XCTFail di un helper con Issue.record di Swift Testing. L'inoltro della posizione di origine deve ancora essere preservato durante quella migrazione.

Diagnostica il sintomo rimanente

Cosa osservi Cosa ispezionare dopo
Il fallimento punta all'interno dell'helper di asserzione Conferma che l'asserzione riceva gli argomenti di posizione catturati
Il fallimento punta all'interno di un helper esterno Conferma che l'helper esterno inoltri la posizione del suo chiamante
Il test Swift Testing passa nonostante un'asserzione XCTest Controlla il supporto della toolchain e la modalità di interoperabilità
Il codice viene eseguito dopo che un'asserzione XCTest fallisce Controlla il flusso di controllo inteso e continueAfterFailure
Nessun test di esempio appare nell'esecuzione Conferma che il file appartenga al target di test unitari e che il piano di test attivo lo includa

Per l'individuazione e la selezione dei test, la test setup guide e la test execution guide di Apple descrivono i target di test e i piani attivi. Per un passaggio cross-framework, usa le regole di interoperabilità documentate sopra prima di cambiare gli argomenti di posizione.

Un helper condiviso utile preserva tre cose: un confronto significativo, una diagnostica legata al chiamante inteso e l'esito del test inteso. Verificali con un errore intenzionale, rimuovi quell'errore e continua a inoltrare la posizione catturata ogni volta che viene introdotto un altro livello di helper.

Fonti