Swift Testing : Le Guide Complet de Swift 6.0 à 6.2
Publié le · Mis à jour le · 25 min
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 :
| Aspect | XCTest | Swift Testing |
|---|---|---|
Syntaxe | Classes, méthodes | Structs, |
Assertions |
|
|
Async |
|
|
Paramétrisation | Manuelle (boucles) |
|
Organisation | Héritage de classes | Tags, traits, suites |
Setup/Teardown |
|
|
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
@Testet@SuiteAssertions
#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
| XCTest | Swift Testing |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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
| Proposal | Titre | Version |
|---|---|---|
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é
Hacking with Swift — What's new in Swift Testing
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.