Swift Testing : Le Guide Complet de Swift 6.0 à 6.2

Publié le · Mis à jour le · 25 min

Wlad
Wlad
Fondateur & Tech Lead Swift

Swift Testing représente une révolution dans l'écosystème de test Apple. Conçu nativement pour Swift, ce framework moderne remplace progressivement XCTest avec une syntaxe expressive, des macros puissantes et une intégration parfaite avec Swift Concurrency. Ce guide exhaustif couvre tout ce que vous devez savoir, des fondamentaux aux fonctionnalités avancées de Swift 6.2.

Pourquoi Swift Testing ?

Après plus de 10 ans de XCTest, Apple a repensé entièrement l'approche du testing. Swift Testing n'est pas une évolution de XCTest — c'est une réécriture complète, pensée pour le Swift moderne.

Les motivations principales :

  • Syntaxe déclarative avec des macros Swift natives

  • Support first-class de async/await et Swift Concurrency

  • Tests paramétrés intégrés nativement

  • Organisation flexible avec tags et traits

  • Messages d'erreur riches et contextuels

  • Open source et évolutif via Swift Evolution

La philosophie centrale : le test ne doit pas être un fardeau. Swift Testing rend l'écriture de tests aussi naturelle que l'écriture du code de production.

Swift Testing vs XCTest

Avant de plonger dans le détail, voici une comparaison rapide des deux approches :

AspectXCTestSwift Testing

Syntaxe

Classes, méthodes test*

Structs, @Test, @Suite

Assertions

XCTAssert* (30+ variantes)

#expect(), #require()

Async

waitForExpectations

async/await natif

Paramétrisation

Manuelle (boucles)

@Test(arguments:)

Organisation

Héritage de classes

Tags, traits, suites

Setup/Teardown

setUp(), tearDown()

init, deinit

Parallélisation

Configuration globale

Par défaut, isolée

UI Tests

Oui

Non (reste XCTest)

Performance Tests

Oui

Non (reste XCTest)

Swift Testing et XCTest peuvent coexister dans le même projet. Les tests UI et de performance restent exclusivement XCTest.

Timeline et évolutions

Swift Testing a évolué rapidement depuis son introduction :

Swift 5.9 — Introduction expérimentale

Première apparition du framework en preview, permettant aux early adopters de tester l'approche.

Swift 6.0 — Septembre 2024

Release officielle avec Xcode 16. Le framework devient production-ready avec :

  • Macros @Test et @Suite

  • Assertions #expect() et #require()

  • Tests paramétrés

  • Traits de base (.enabled, .disabled, .bug, .timeLimit)

  • Tags pour l'organisation

Swift 6.1 — Mars 2025

Trois proposals majeures intégrées :

  • ST-0005 : Ranged confirmations — Vérifier qu'un callback est appelé N fois

  • ST-0006 : Return errors from expect throws — Récupérer l'erreur lancée

  • ST-0007 : Test Scoping Traits — Code before/after sans état global

Swift 6.2 — Septembre 2025

Évolutions significatives avec Xcode 26 :

  • ST-0008 : Exit Tests — Tester les crashes (precondition, fatalError)

  • ST-0009 : Attachments — Joindre fichiers aux résultats de test

  • ST-0010 : evaluate() sur ConditionTrait

  • Raw identifier display names avec backticks

Roadmap future

En discussion active :

  • ST-0011 : Issue Handling Traits — Modifier/filtrer les issues avant rapport

  • Test Issue Warnings — Issues qui ne font pas échouer la suite

Installation et configuration

Package.swift

Pour un Swift Package, ajoutez la dépendance de test :

Xcode

Dans Xcode 16+, Swift Testing est disponible automatiquement. Créez simplement un fichier dans votre target de test :

Prérequis système

Pour développer avec Swift Testing :

  • macOS 14.5+ pour Xcode 16

  • macOS 15+ pour Xcode 26 (Swift 6.2)

  • Le code testé peut cibler des versions iOS/macOS plus anciennes

Coexistence avec XCTest

Vous pouvez avoir des fichiers XCTest et Swift Testing dans le même target :

Les deux frameworks s'exécutent ensemble via swift test ou le Test Navigator Xcode.

Syntaxe fondamentale

@Test — Déclarer un test

La macro @Test marque une fonction comme test :

Contrairement à XCTest, pas besoin de préfixer par test. Le nom de fonction est libre.

Display names

Ajoutez un nom lisible pour les rapports :

Raw identifiers (Swift 6.2)

Swift 6.2 permet d'utiliser des backticks pour des noms expressifs :

Le nom de fonction devient directement le display name, sans duplication.

@Suite — Organiser les tests

Regroupez les tests liés dans une suite :

Les suites peuvent être imbriquées :

Assertions modernes

#expect() — Vérification standard

#expect() est l'assertion principale. Elle accepte n'importe quelle expression booléenne :

En cas d'échec, Swift Testing affiche un message contextuel riche montrant les valeurs réelles.

#require() — Préconditions obligatoires

#require() arrête le test immédiatement si la condition échoue. Utile pour les préconditions :

#require() peut aussi déballer des optionnels :

Tester les erreurs

Pour vérifier qu'une fonction lance une erreur :

Récupérer l'erreur (Swift 6.1 — ST-0006)

Swift 6.1 permet de récupérer l'erreur pour des assertions supplémentaires :

Correspondance XCTest → Swift Testing

XCTestSwift Testing

XCTAssertTrue(x)

#expect(x)

XCTAssertFalse(x)

#expect(!x)

XCTAssertEqual(a, b)

#expect(a == b)

XCTAssertNotEqual(a, b)

#expect(a != b)

XCTAssertNil(x)

#expect(x == nil)

XCTAssertNotNil(x)

#expect(x != nil)

XCTAssertGreaterThan(a, b)

#expect(a > b)

XCTAssertThrowsError(expr)

#expect(throws: Error.self) { expr }

XCTUnwrap(x)

try #require(x)

XCTFail("message")

Issue.record("message")

Tests asynchrones

Swift Testing supporte async/await nativement :

Exemple complet avec API

Timeouts

Utilisez le trait .timeLimit pour éviter les tests qui bloquent :

Tests paramétrés

Les tests paramétrés exécutent le même test avec différentes entrées :

Ce test s'exécute 5 fois, une fois par argument.

Arguments multiples

Utiliser CaseIterable

Pour les enums, utilisez allCases :

Combinaisons de paramètres

Testez toutes les combinaisons de deux ensembles :

Zip pour paires correspondantes

Pour tester des paires entrée/sortie :

Traits — Configuration des tests

Les traits modifient le comportement d'un test ou d'une suite.

.enabled(if:) et .disabled()

Activez ou désactivez conditionnellement :

.bug() — Référencer des issues

Documentez les bugs associés :

.timeLimit() — Timeout

Définissez une limite de temps :

evaluate() pour ConditionTrait (Swift 6.2)

Swift 6.2 permet d'évaluer les conditions en dehors des tests :

Tags — Organisation flexible

Les tags permettent de catégoriser et filtrer les tests.

Créer des tags

Définissez vos tags dans une extension :

Appliquer des tags

Filtrer en ligne de commande

Vue tags dans Xcode

Dans le Test Navigator (⌘-6), cliquez sur l'icône de tag pour voir vos tests organisés par tags plutôt que par fichier.

Organisation avancée

Fixtures avec init/deinit

Utilisez l'initialisation de la struct pour le setup :

Chaque test reçoit une instance fraîche de la suite, donc une base de données propre.

Accéder au test courant

Pour le logging ou debugging :

CustomTestStringConvertible

Personnalisez l'affichage des types dans les rapports :

Confirmations et expectations async

confirmation() — Vérifier les callbacks

Pour les APIs callback-based :

Ranged confirmations (Swift 6.1 — ST-0005)

Vérifiez qu'un callback est appelé un nombre précis de fois :

withKnownIssue() — Bugs connus

Marquez un test comme ayant un bug connu sans le désactiver :

Le test s'exécute, l'échec est enregistré mais ne fait pas échouer la suite.

Test Scoping Traits (Swift 6.1 — ST-0007)

Les Test Scoping Traits permettent d'exécuter du code before/after sans état global mutable.

Définir un scope trait

Utiliser le scope

Avantages :

  • Pas d'état global mutable

  • Compatible avec la parallélisation

  • Réutilisable entre suites

  • Utilise Structured Concurrency

Exit Tests (Swift 6.2 — ST-0008)

Les Exit Tests permettent de vérifier que du code termine le processus (crash, precondition, fatalError).

Pourquoi c'est révolutionnaire

Avant Swift 6.2, tester un crash était quasi impossible. Il fallait créer un CLI séparé et utiliser des outils externes. Maintenant :

Exemple pratique

Comment ça marche

Le code dans le bloc s'exécute dans un processus séparé. Swift Testing vérifie le code de sortie du processus.

Attachments (Swift 6.2 — ST-0009)

Les Attachments permettent de joindre des fichiers aux résultats de test pour faciliter le diagnostic.

Joindre une image

Joindre du JSON

Joindre des logs

Les attachments apparaissent dans les rapports Xcode et CI, facilitant grandement le diagnostic des échecs.

Migration depuis XCTest

Stratégie progressive

Ne migrez pas tout d'un coup. Approche recommandée :

  • Nouveaux tests → Swift Testing

  • Tests refactorisés → Swift Testing

  • Tests stables → Migrer progressivement

  • Tests UI/Performance → Restent XCTest

Exemple de migration

Avant (XCTest) :

Après (Swift Testing) :

Ce qui reste en XCTest

Certaines fonctionnalités restent exclusives à XCTest :

  • Tests UI avec XCUITest

  • Tests de performance avec measure {}

  • Certaines intégrations CI spécifiques

  • XCTActivity pour la hiérarchie de logs

Intégration CI/CD

Xcode Cloud

Swift Testing fonctionne nativement avec Xcode Cloud. Aucune configuration spéciale requise.

GitHub Actions

Rapports de test

Swift Testing supporte plusieurs formats de rapport :

Runtime Issue Detection (Xcode 26)

Xcode 26 introduit la détection automatique des runtime issues dans les tests :

  • Thread Sanitizer violations

  • Memory leaks

  • Main thread violations

Ces issues apparaissent comme warnings ou errors selon votre configuration.

Bonnes pratiques

Conventions de nommage

Utilisez des noms descriptifs en anglais :

Un test = une assertion logique

Préférez plusieurs tests ciblés à un gros test :

Isolation des tests

Chaque test doit être indépendant :

Performance des tests

Parallélisez autant que possible (c'est le défaut). Pour les tests qui ne peuvent pas être parallélisés :

Ressources officielles

Documentation Apple

WWDC Sessions

  • WWDC 2024 — Meet Swift Testing : Introduction complète

  • WWDC 2024 — Go further with Swift Testing : Fonctionnalités avancées

  • WWDC 2025 — What's new in Swift Testing : Exit tests, Attachments

GitHub

Swift Evolution Proposals

ProposalTitreVersion

ST-0005

Ranged confirmations

Swift 6.1

ST-0006

Return errors from expect throws

Swift 6.1

ST-0007

Test Scoping Traits

Swift 6.1

ST-0008

Exit tests

Swift 6.2

ST-0009

Attachments

Swift 6.2

ST-0010

evaluate() on ConditionTrait

Swift 6.2

ST-0011

Issue Handling Traits

En review

Communauté

Swift Testing représente l'avenir du testing sur les plateformes Apple. Son adoption progressive, sa coexistence avec XCTest et ses évolutions rapides en font un choix évident pour tout nouveau projet Swift.