Le tutoriel officiel d’Apple sur Swift Testing prend l’exemple d’une application de score et présente notamment les annotations @Test et les vérifications #expect (exemple pédagogique d’Apple). Pour tester un projet SwiftUI, commencez par isoler une règle de logique, puis placez un test qui vérifie cette règle dans un test target et exécutez-le. Un test unitaire vérifie le comportement du code ; il ne remplace pas le contrôle des boutons, de l’affichage ni du parcours dans l’application.

Ce guide s’adresse aux étudiants qui écrivent leurs premiers tests pour un projet SwiftUI et découvrent les test targets de Xcode.
Il convient aussi aux personnes qui savent lancer leur application, mais veulent contrôler un calcul ou un changement d’état.
Enfin, les personnes qui travaillent sur un Mac d’école ou à distance y trouveront des repères pour conserver un résultat de test vérifiable.

01

Avant d’ouvrir les réglages, choisissez une règle de votre projet

Prenez une action précise, par exemple l’ajout d’un point, la validation d’une saisie ou le calcul d’un total. Le meilleur premier test porte sur une règle dont l’entrée et le résultat attendu se décrivent sans devoir ouvrir une fenêtre ni appuyer réellement sur un bouton.

Un écran peut sembler correct tout en appliquant une règle erronée. Un texte affiche « 1 point », mais la variable conserve une valeur différente ; ou une entrée négative fait passer un compteur sous zéro alors que le cours demande de le bloquer. Le contrôle visuel ne révèle pas toujours cette erreur, surtout si l’état fautif n’est pas visible immédiatement.

Repérez les calculs qui se trouvent dans une structure View. Si un bouton modifie une valeur, demandez-vous si la règle de modification peut être déplacée dans un type ou une fonction que le test peut appeler directement. La vue gardera la responsabilité de présenter l’état et de réagir aux actions ; la logique séparée pourra être vérifiée sans lancer cette interaction.

Comment choisir le premier comportement à vérifier ? Notez ce qui entre, l’action effectuée et le résultat attendu. Cette méthode revient à préparer une petite correction de devoir : la consigne donne les données, l’opération est la règle du programme, et le résultat attendu sert de critère de notation.

Choix du premier test Exemple de départ Ce que le test peut vérifier
Calcul isolé Un total reçoit une nouvelle valeur La valeur calculée correspond à la règle
Validation Une saisie est vide ou incorrecte Le résultat indique si la saisie est acceptée
Changement d’état Un compteur reçoit une action L’état obtenu respecte le comportement prévu
Vue complète Un bouton modifie l’écran Le rendu et l’interaction demandent un contrôle d’interface séparé

Cette séparation ne signifie pas qu’il faut réécrire tout le projet avant de commencer. Déplacez uniquement la règle que vous voulez rendre testable ; gardez la vue aussi simple que possible et vérifiez que l’application continue de compiler après le changement. Si le calcul dépend directement de @State, d’un élément visuel ou d’un objet difficile à construire, commencez par extraire une fonction indépendante plutôt que par remanier l’architecture entière.

02

Organisez la règle comme une opération vérifiable

Voici un petit modèle de score, indépendant de l’interface. Il accepte un score initial et empêche qu’une valeur négative soit conservée :

struct ScoreModel {
    private(set) var score: Int

    init(score: Int = 0) {
        self.score = max(0, score)
    }

    mutating func add(_ points: Int) {
        score = max(0, score + points)
    }
}

Dans une vue SwiftUI, un bouton peut appeler add(1) et un texte peut afficher score. Le modèle, lui, n’a pas besoin de connaître le bouton ni la façon dont le texte est dessiné. Ce découpage permet de vérifier le calcul directement ; il ne prouve pas encore que le bouton appelle la bonne méthode ou que la valeur s’affiche correctement.

Pour l’exemple, le résultat attendu après l’ajout d’un point à un score initial de zéro est 1. Une entrée négative assez importante pour faire passer le résultat sous zéro doit être ramenée à 0. Ces valeurs appartiennent aux règles définies dans le code d’exemple, et non à une exigence universelle de SwiftUI : adaptez-les aux consignes du projet.

À retenir : un test vérifie le comportement prévu par votre projet, pas une règle de conception imposée à toutes les applications. Si votre exercice autorise les scores négatifs, le résultat attendu doit refléter cette consigne.

Dans ce contexte, un test target est la partie distincte du projet destinée au code de test ; ce n’est ni un deuxième écran ni une copie de l’application. Apple documente l’ajout de tests à un projet Xcode et la configuration de nouvelles cibles dans ses pages sur l’ajout de tests et la configuration d’un target.

03

Dans Xcode 27, repérez le bon emplacement avant d’écrire le test

Un projet créé avec une configuration de tests peut déjà contenir une cible prévue à cet effet. Dans un projet existant, vérifiez plutôt la liste des targets et la cible associée au fichier de test. Les noms exacts et l’emplacement des commandes peuvent évoluer ; en cas de différence avec une capture d’écran trouvée ailleurs, appuyez-vous sur la documentation Apple et sur l’organisation visible dans votre projet, sans supposer qu’un ancien menu est encore au même endroit.

Situation dans le projet Vérification dans Xcode Décision
Le projet contient déjà une cible de tests Vérifiez que le fichier de test lui appartient Utilisez la cible existante si elle est configurée pour le projet
Le projet ne présente aucune cible de tests Consultez les réglages du projet et la documentation Apple sur les targets Ajoutez une cible adaptée au projet avant d’écrire le test
Le fichier existe, mais aucun test n’apparaît Vérifiez son appartenance à la cible et sa déclaration Corrigez l’emplacement ou la déclaration avant de modifier la logique

Un même fichier peut être visible dans le navigateur du projet sans être compilé pour la cible de tests. C’est pourquoi il faut sélectionner le fichier et contrôler son appartenance à la cible, au lieu de déduire son rôle de son seul nom ou de son dossier. Le module de l’application doit également être importé dans le fichier de test selon la configuration du projet. Apple explique comment ajouter des tests à un projet Xcode ; suivez cette procédure pour le type de projet utilisé, notamment si la configuration initiale a été modifiée.

Dans un fichier de test Swift Testing, import Testing donne accès au cadre de test. L’import du module de l’application permet ensuite d’utiliser le type testé ; selon le niveau d’accès choisi pour ce type, le projet peut nécessiter @testable import NomDuModule. Remplacez ce nom par celui du module réel, visible dans les réglages du target : un nom de dossier ou le nom affiché de l’application n’est pas nécessairement identique.

Où placer le fichier pour que Xcode le découvre ? Placez-le dans le target de tests, et non uniquement dans le target principal de l’application. Un fichier correctement nommé mais associé à la mauvaise cible peut rester absent de l’exécution des tests, même si l’application se lance normalement.

04

Écrivez le test, puis comparez la valeur obtenue au résultat prévu

Les formes @Test et #expect sont utilisées dans la documentation et les exemples Apple de Swift Testing. @Test marque une fonction comme test ; #expect exprime la condition que le résultat doit satisfaire. La documentation d’Apple décrit aussi les attentes et conditions de Swift Testing.

import Testing
@testable import NomDuModule

struct ScoreModelTests {
    @Test
    func ajoutDUnPointAugmenteLeScore() {
        var model = ScoreModel()

        model.add(1)

        #expect(model.score == 1)
    }

    @Test
    func unScoreNeDevientPasNegatif() {
        var model = ScoreModel(score: 1)

        model.add(-3)

        #expect(model.score == 0)
    }
}

Remplacez NomDuModule par le nom du module de l’application ; si le type testé est exposé avec un niveau d’accès différent, adaptez l’import aux réglages du projet. Le premier cas prépare un modèle, appelle la méthode et contrôle le score. Le second teste une situation limite : une entrée négative qui ferait normalement passer le résultat sous zéro. Une situation limite, ou cas de bord, est simplement un cas moins courant situé près d’une limite définie par la règle.

Le code teste ici deux comportements du modèle, pas le fonctionnement visuel de l’écran. Apple présente Swift Testing comme un cadre de test pour le code Swift ; sa présentation officielle de Swift Testing et son tutoriel consacré à une application de score permettent de vérifier les formes de code employées.

Résultat de l’exécution Interprétation possible Contrôle suivant
Le test passe Le comportement vérifié correspond au résultat attendu dans ce cas Gardez le test et vérifiez séparément le parcours dans l’application
Le test échoue avec une valeur différente La règle, la préparation ou le résultat attendu ne concordent pas Comparez les entrées, l’opération et l’assertion
Aucun test n’est détecté Le fichier ou la fonction n’est peut-être pas rattaché ou déclaré comme attendu Contrôlez la cible, l’import et la déclaration du test
La cible ne s’exécute pas correctement Le problème peut concerner la configuration ou l’environnement de test Examinez le message d’erreur et les réglages avant de changer le code métier
05

Lancez les tests et remontez à la cause au lieu de deviner

Dans Xcode, lancez l’exécution des tests depuis les commandes prévues pour le projet ou depuis l’action associée à un test. Les libellés précis dépendent de la version et de la configuration : Apple décrit le lancement et l’interprétation des résultats dans son guide Exécuter les tests et interpréter les résultats. Après l’exécution, lisez le statut et le détail associé à chaque test ; le simple fait que la compilation de l’application réussisse ne confirme pas que les tests ont tourné.

Pourquoi l’application démarre-t-elle alors qu’aucun test Swift Testing n’apparaît ? Commencez par vérifier que le fichier appartient au target de tests. Vérifiez ensuite que le fichier importe Testing et que la fonction porte bien la déclaration attendue par le cadre de test. Si le target ne compile pas, lisez d’abord son erreur de compilation : elle peut empêcher la découverte des tests avant même que la logique soit exécutée.

Lorsque le test apparaît mais échoue, séparez le diagnostic en trois pistes concrètes. D’abord, assurez-vous que le target de tests s’est réellement exécuté et que le résultat affiché correspond au bon schéma. Ensuite, comparez les données préparées avec celles que vous pensiez utiliser. Enfin, examinez la méthode testée et l’assertion : le résultat attendu correspond-il toujours à la consigne du devoir ?

Évitez de supprimer des fichiers ou de réinstaller Xcode comme premier réflexe. Ces gestes ne corrigent ni un fichier exclu de la cible ni une assertion qui attend une mauvaise valeur. Le message d’échec, la cible sélectionnée et le cas de test constituent les premiers éléments à confronter.

Rappel de diagnostic : si le test n’est pas découvert, cherchez d’abord un problème de cible ou de déclaration ; s’il est découvert mais échoue, comparez les entrées, le comportement du modèle et le résultat attendu.

Sur un Mac utilisé à l’école ou à distance, gardez le projet, le nom du target et le compte rendu de l’exécution dans un état que vous pourrez retrouver. Vérifiez aussi que le Mac dispose d’une version de système compatible avec la version de Xcode retenue : Apple publie ces exigences sur sa page Configuration système requise pour Xcode. Si vous utilisez un environnement distant pour suivre un cours, la page de commande d’un Mac distant NodeMini donne des informations sur cette option ; vérifiez les modalités présentes sur la page avant de choisir un environnement de travail.

06

Terminez par un contrôle logique, puis par une vérification de l’interface

Avant de considérer l’exercice terminé, relancez le test après toute modification du modèle. Le comportement normal et une situation limite doivent correspondre aux règles réellement demandées ; si le cours précise d’autres cas importants, ajoutez ceux qui peuvent être vérifiés sans dépendre de l’affichage.

Ensuite, exécutez l’application et vérifiez le parcours visuel : le bouton déclenche-t-il la bonne action, la valeur affichée se met-elle à jour, et l’état présenté à l’écran correspond-il au résultat du modèle ? Un test logique réussi ne permet pas de conclure que l’écran est correct, pas plus qu’une interface qui semble juste ne prouve que le calcul est fiable.

Faut-il encore vérifier l’application dans le simulateur après un test unitaire réussi ? Oui, si le devoir demande de valider l’interface ou les interactions. Le test du modèle vérifie une règle de code ; le simulateur permet de parcourir l’application et d’observer ce que voit l’utilisateur. Si la consigne exige une validation sur appareil réel, le simulateur ne la remplace pas : suivez le niveau de contrôle demandé par l’enseignant.

Vérification finale Ce qu’elle confirme Ce qu’elle ne confirme pas à elle seule
Test de logique réussi Le comportement testé correspond à l’attente définie Le rendu visuel et toutes les interactions
Application lancée dans le simulateur Le parcours testé s’affiche et peut être essayé dans cet environnement Le comportement sur un appareil réel si le cours l’exige
Validation demandée par le cours Le livrable répond au contrôle précisé dans la consigne Les cas qui n’ont pas été exécutés ou vérifiés

Si vous disposez déjà d’un Mac compatible avec la version de Xcode utilisée, poursuivre localement est souvent le chemin le plus direct : vous gardez l’accès physique à la machine et pouvez suivre les exercices sans dépendre d’une connexion distante. À l’inverse, travailler uniquement sur Windows, partager un ordinateur de cours ou devoir installer un macOS non adapté peut compliquer l’accès à Xcode, la conservation du projet et les vérifications en simulateur. Pour comparer les solutions avant de continuer, la page NodeMini consacrée aux Mac distants peut aider à déterminer si un environnement macOS temporaire correspond à votre cours. Si le besoin se limite à quelques séances ou à un exercice, louer un Mac peut éviter l’achat d’une machine ; pour une utilisation quotidienne durable ou un besoin d’accès physique, un Mac personnel sera plus approprié.