Accueil / Blog / Comment configur
ENGINEERING_BLOG · 2026.08.24

Comment configurer un serveur de tests automatisés iOS ? Tutoriel Mac distant 2026

Apple documente explicitement la séparation entre la préparation d’un produit à tester et son exécution avec build-for-testing puis test-without-building dans sa documentation de ligne de commande【la documentation Apple sur la construction et les tests en ligne de commande】(https://developer.apple.com/library/archive/technotes/tn2339/_index.html?product=WM). Cette séparation conduit à une décision simple : ne migrez pas tout votre développement sur le Mac. Gardez le codage sur Windows ou Linux, puis utilisez un serveur de tests automatisés iOS distant pour compiler, lancer XCTest ou les tests d’interface et conserver les preuves d’échec.

Cette méthode convient aux développeurs indépendants qui écrivent du code multiplateforme sans posséder de Mac local, aux auteurs d’applications qui veulent déporter des tests longs, ainsi qu’aux petites équipes qui recherchent une machine récupérable sans déployer immédiatement une plateforme d’intégration complexe.

SECTION 01 Avant de commencer : fixez le périmètre du serveur

Le premier risque n’est pas une commande mal écrite. C’est de demander à la machine distante de résoudre un problème qui devrait rester local, ou de lancer plusieurs variantes de simulateur avant d’avoir obtenu un premier test fiable.

Votre architecture peut rester volontairement étroite :

Activité Environnement conseillé Critère de passage
Édition du code et revue des changements Votre poste habituel Le dépôt reste exploitable sans session distante
Récupération des dépendances et compilation de test Mac distant La commande retourne un état de sortie interprétable
Exécution de XCTest et des tests d’interface Simulateur sur le Mac distant Le même scénario peut être relancé avec le même état
Lecture des résultats et diagnostic Poste local après transfert Le paquet xcresult et les journaux sont accessibles
Réexécution ciblée après échec Mac distant Un seul test ou une classe peut être relancé sans tout reconstruire

Avant toute installation, notez le type de test prévu, sa fréquence, la version de système simulée, le schéma partagé utilisé par le projet et le niveau de réussite attendu. Un test unitaire rapide, une suite d’interface qui dépend de permissions et une régression complète ne sollicitent pas le serveur de la même manière.

Utilisez le projet existant comme référence plutôt que de choisir une configuration théorique. Le Scheme, le Test Plan, les destinations et les dépendances déjà validés par votre équipe constituent votre véritable cahier des charges. La matrice officielle des exigences système de Xcode doit ensuite confirmer que macOS, Xcode et le Simulator Runtime retenu peuvent coexister.

Sans Mac local, peut-on exécuter des tests unitaires et des tests d’interface iOS ? Oui, à condition que le Mac distant fournisse macOS, Xcode, le simulateur approprié et un accès d’administration suffisant. Le poste Windows ou Linux peut éditer le code et déclencher la tâche, mais la compilation avec Xcode et l’exécution du simulateur restent sur l’hôte Mac.

Choisissez le mode d’exploitation avant l’achat

  • Si vous lancez une régression seulement après une fonctionnalité importante, sélectionnez un Mac activé à la demande et transférez les résultats à la fin de la tâche.
  • Si vous exécutez des tests chaque jour, programmez des suites nocturnes ou devez retrouver rapidement une session interrompue, comparez une location maintenue en permanence.
  • Si vous avez besoin de plusieurs appareils simulés, ne supposez pas que l’exécution parallèle sera automatiquement plus rapide : les conflits de données, la mémoire disponible et la stabilité des tests doivent être mesurés sur votre projet.
  • Si vous devez connecter un appareil physique, une clé matérielle ou un accessoire audio et vidéo, vérifiez explicitement la prise en charge de l’accès physique avant de retenir le distant.

SECTION 02 Première étape : verrouillez la chaîne Xcode sur le Mac distant

Commencez par une session d’administration distincte de votre compte personnel. Créez un compte réservé aux tests, un répertoire de travail et un emplacement temporaire pour DerivedData et les paquets de résultats. Utilisez des noms manifestement génériques dans vos scripts, par exemple :

  • PROJET_EXEMPLE
  • SCHEME_TEST
  • PLAN_RAPIDE
  • APP_TEST
  • /Users/COMPTE_TEST/workspace/
  • DESTINATION_SIMULATEUR

Ne placez pas de jeton, de certificat privé ou de mot de passe directement dans le dépôt. Même lorsque les tests ne produisent pas d’application distribuable, les journaux peuvent révéler des chemins locaux, des identifiants ou des paramètres internes.

Vérifiez ensuite, dans cet ordre :

  • la version de macOS acceptée par la version de Xcode installée ;
  • la présence des outils en ligne de commande ;
  • le chemin actif sélectionné par xcode-select ;
  • la disponibilité du Simulator Runtime nécessaire ;
  • l’existence du périphérique simulé indiqué dans le Scheme ou le Test Plan.

La documentation Apple explique comment ajouter un Simulator Runtime. Ne téléchargez pas plusieurs environnements « au cas où » : chaque Runtime supplémentaire complique l’identification de la destination réellement utilisée et augmente l’espace occupé, sans améliorer la fiabilité d’une suite qui n’en a besoin que d’un seul.

Une vérification minimale peut ressembler à ceci, en remplaçant tous les éléments entre crochets :

xcode-select -p
xcodebuild -version
xcrun simctl list devices available
xcodebuild \
  -workspace "[PROJET_EXEMPLE].xcworkspace" \
  -scheme "[SCHEME_TEST]" \
  -showdestinations

Ces commandes ne prouvent pas encore que votre application peut être testée. Elles prouvent seulement que le serveur pointe vers les outils attendus et qu’une destination potentielle est visible.

Séparez aussi les tâches exécutées par SSH des vérifications nécessitant une session graphique. La commande de test peut être déclenchée à distance, mais le démarrage du simulateur, l’état d’une fenêtre et l’observation d’un blocage doivent être validés sur votre projet. Apple décrit l’usage de tests en ligne de commande sur une machine distante dans sa documentation consacrée à l’automatisation.

Le serveur de test iOS doit-il conserver une session graphique ouverte ? Ne l’affirmez pas sans essai. Une suite pilotée par xcodebuild peut être déclenchée en ligne de commande, mais les tests d’interface dépendent du lancement correct du simulateur et certaines opérations de diagnostic sont plus simples dans une session graphique. Testez le démarrage après connexion SSH, après fermeture de la fenêtre distante et après redémarrage du Mac ; retenez le comportement réellement observé avec votre Scheme.

SECTION 03 Deuxième étape : faites réussir un seul point d’entrée

Ne commencez pas par une suite complète. Partagez un Scheme dédié aux tests, sélectionnez une destination déterministe et lancez d’abord un test suffisamment petit pour distinguer un problème de projet d’un problème de serveur.

Voici une séquence volontairement générique :

set -o pipefail

xcodebuild \
  -workspace "[PROJET_EXEMPLE].xcworkspace" \
  -scheme "[SCHEME_TEST]" \
  -destination 'platform=iOS Simulator,id=[IDENTIFIANT_SIMULATEUR]' \
  -testPlan "[PLAN_RAPIDE]" \
  -derivedDataPath "/Users/COMPTE_TEST/tmp/derived-data" \
  test \
  -resultBundlePath "/Users/COMPTE_TEST/results/test.xcresult" \
  2>&1 | tee "/Users/COMPTE_TEST/results/console.log"

status=${PIPESTATUS[0]}
exit "$status"

Cette forme répond à trois besoins distincts : le processus de test conserve son code de sortie, la console est enregistrée et un paquet xcresult est produit. La référence Apple sur l’exécution des tests et l’interprétation des résultats confirme que les résultats et les journaux peuvent être consultés dans l’environnement Xcode.

Pour réduire le périmètre après un premier échec, utilisez only-testing sur une cible ou un identifiant de test connu :

xcodebuild \
  -workspace "[PROJET_EXEMPLE].xcworkspace" \
  -scheme "[SCHEME_TEST]" \
  -destination 'platform=iOS Simulator,id=[IDENTIFIANT_SIMULATEUR]' \
  -only-testing:"[CIBLE_TEST]/[CLASSE_TEST]/[METHODE_TEST]" \
  test

Ne transformez pas cette restriction en configuration permanente. Elle sert à localiser l’erreur et à réduire le temps de diagnostic, tandis que le Test Plan doit séparer les usages : boucle rapide, régression complète et contrôle avant livraison. Apple recommande d’organiser les tests avec des Test Plans, ce qui permet de modifier la composition d’une suite sans dupliquer inutilement les réglages du projet.

Comment automatiser XCTest avec xcodebuild sur un Mac distant ? Préparez le dépôt, sélectionnez un Scheme et une destination explicites, lancez test, capturez PIPESTATUS et archivez le résultat. Pour une suite plus lourde, dissociez la compilation avec build-for-testing de l’exécution avec test-without-building, conformément aux indications de la note technique Apple sur les commandes de construction et de test.

SECTION 04 Troisième étape : rendez l’état du simulateur reproductible

Un test d’interface qui réussit une fois ne constitue pas encore un service fiable. Le simulateur peut conserver une autorisation, une base locale, une préférence de langue, un écran d’accueil différent ou un état de navigation laissé par l’exécution précédente.

Définissez dans votre Test Plan ou votre préparation de tâche :

  • le type de périphérique simulé ;
  • le Runtime et l’identifiant de destination ;
  • la langue et la région ;
  • les données de test injectées au démarrage ;
  • les autorisations attendues ;
  • la stratégie de nettoyage entre deux exécutions.

Le but n’est pas de réinitialiser agressivement le système à chaque commande. Un effacement complet peut supprimer les journaux utiles à l’analyse, masquer un défaut de nettoyage de l’application ou modifier un problème que vous cherchez justement à reproduire. Commencez par supprimer les données créées par le test lui-même, puis élargissez le nettoyage uniquement lorsque l’état partagé est identifié comme cause.

Classez chaque échec dans une catégorie avant de modifier la machine :

  • application : l’interface ou la logique ne respecte pas le scénario ;
  • test : une attente est trop courte, un sélecteur est fragile ou une donnée manque ;
  • simulateur : état résiduel, démarrage incomplet ou Runtime incorrect ;
  • session distante : perte de connexion, processus interrompu ou environnement graphique indisponible.

Cette classification évite de conclure trop vite que le serveur manque de puissance. Une attente d’élément mal synchronisée peut échouer sur un Mac rapide comme sur un autre hôte, tandis qu’un simulateur laissé dans un état inattendu peut donner l’impression d’un défaut de performance.

Pour les projets audio, vidéo ou graphiques, ajoutez des données de test contrôlées plutôt que des fichiers personnels variables. Une séquence vidéo fixe, un projet audio minimal et des ressources versionnées rendent les régressions plus comparables ; ils évitent aussi que la bande passante de votre session distante soit confondue avec le temps réel de traitement du test.

SECTION 05 Quatrième étape : conservez les preuves, pas seulement le statut

Une tâche qui affiche « échec » puis supprime son répertoire de travail ne permet pas de maintenir un serveur. Conservez au minimum :

  • le paquet xcresult ;
  • le journal complet de la console ;
  • les captures d’écran ou vidéos produites par les tests d’interface ;
  • le commit ou l’identifiant de version testé ;
  • la destination et le Test Plan utilisés ;
  • le code de sortie de la commande ;
  • la raison connue du nettoyage ou du redémarrage.

Un paquet xcresult peut contenir les résultats de test, la couverture et des journaux associés, mais il ne garantit pas qu’une cause unique sera visible pour chaque échec. Apple décrit le format et les outils associés dans ses notes sur xcresult et xcresulttool. Vous devez donc conserver les éléments périphériques, notamment la sortie console et les captures liées au scénario.

L’export peut être organisé dans un répertoire par exécution :

RUN_ID="[IDENTIFIANT_EXECUTION]"
RESULT_DIR="/Users/COMPTE_TEST/results/${RUN_ID}"

mkdir -p "$RESULT_DIR"

xcodebuild \
  -workspace "[PROJET_EXEMPLE].xcworkspace" \
  -scheme "[SCHEME_TEST]" \
  -destination 'platform=iOS Simulator,id=[IDENTIFIANT_SIMULATEUR]' \
  test \
  -resultBundlePath "${RESULT_DIR}/tests.xcresult" \
  2>&1 | tee "${RESULT_DIR}/console.log"

Ne réutilisez pas le même chemin de résultat pour deux tâches simultanées. Vous risqueriez d’écraser le diagnostic d’un test avec celui d’un autre. De même, définissez une politique de conservation : gardez plus longtemps les échecs non analysés et réduisez progressivement les artefacts des exécutions réussies, après avoir vérifié que votre stockage ne se remplit pas silencieusement.

Comment consulter un xcresult produit à distance ? Laissez le Mac produire le paquet, puis transférez-le vers votre poste pour l’ouvrir avec Xcode ou l’inspecter avec les outils prévus par Apple. Le résultat doit être associé au journal, au commit et à la destination ; sans ce contexte, un rapport isolé est souvent insuffisant pour reproduire le défaut.

Ajoutez enfin une règle claire pour l’échec : notification, conservation du paquet, possibilité de relancer un seul test et signalement de la différence entre échec fonctionnel et tâche interrompue. Une coupure SSH ne doit pas être enregistrée comme un échec XCTest sans preuve.

SECTION 06 Cinquième étape : utilisez la répétition pour mesurer la fragilité

Lorsque le scénario de base fonctionne, activez la répétition des tests sur un périmètre réduit. Cette fonction sert à révéler les tests instables ; elle ne doit pas être utilisée pour maquiller un résultat en déclarant la suite fiable dès qu’une tentative réussit. La documentation Apple sur la répétition des tests doit être vérifiée lorsque le comportement de la commande ou de l’interface évolue.

Interprétez les résultats selon la cause :

  • échec toujours identique : défaut probablement déterministe dans l’application ou le test ;
  • échec variable avec données identiques : synchronisation, dépendance externe ou état du simulateur à examiner ;
  • échec après plusieurs suites : résidu, fuite de ressource ou accumulation dans le répertoire de travail ;
  • échec uniquement après fermeture de session : chaîne de lancement distante à corriger.

Ne choisissez le parallélisme qu’après cette étape. Deux tests qui écrivent dans la même base, utilisent le même compte fictif ou attendent une ressource exclusive peuvent s’influencer mutuellement. Commencez en série, mesurez les conflits, puis isolez les destinations et les données avant d’essayer une exécution parallèle.

SECTION 07 À la fin de la première semaine : validez le serveur comme un service

Votre jalon réel n’est pas « la commande a réussi ». C’est la capacité à refaire le parcours complet sans intervention manuelle :

  • récupérer le dépôt avec une référence précise ;
  • restaurer les dépendances ;
  • sélectionner le bon Xcode et le bon simulateur ;
  • exécuter le Scheme rapide ;
  • exécuter la suite d’interface ;
  • exporter xcresult et les journaux ;
  • relancer un test précis après échec ;
  • redémarrer la machine puis accepter une nouvelle tâche.

Contrôlez séparément la croissance de DerivedData, les simulateurs abandonnés, les paquets de résultats conservés et les journaux de connexion. Supprimez un cache seulement après avoir défini ce qu’il contient et ce que sa suppression invalide. La suppression de DerivedData peut forcer une reconstruction ; l’effacement d’un simulateur peut supprimer des données utiles à la reproduction. Dans les deux cas, exportez d’abord le dossier de diagnostic et inscrivez l’opération dans le journal de maintenance.

Si votre équipe veut ensuite déclencher ces tâches depuis un service d’intégration, gardez le serveur de tests indépendant pendant la validation. Vous saurez ainsi si l’échec vient du projet, du Mac ou de l’orchestrateur. La documentation Apple sur les actions d’un flux de travail de tests peut servir de référence pour comparer les étapes, sans transformer ce tutoriel en guide de plateforme d’intégration.

La décision après validation

  • Choisissez l’usage à la demande si les tests sont occasionnels, si une seule destination suffit et si vous pouvez attendre le démarrage avant une régression.
  • Choisissez un Mac distant permanent si les tests doivent s’exécuter chaque jour, si les artefacts doivent rester immédiatement disponibles ou si une tâche nocturne doit redémarrer sans présence humaine.
  • Restez en local si vous possédez déjà un Mac correctement compatible et que l’accès physique, les périphériques ou le débogage visuel dominent votre besoin.
  • Séparez les niveaux de test si les tests unitaires sont fréquents mais les tests d’interface plus rares : le premier groupe peut être déclenché rapidement, tandis que le second utilise une machine distante réservée aux régressions.

L’ancien fonctionnement « poste Windows ou Linux plus accès ponctuel à une machine quelconque » devient vite limité : l’état du simulateur n’est pas documenté, les journaux disparaissent après la session, et une déconnexion peut interrompre une suite sans mécanisme de reprise. Acheter un Mac dédié règle une partie de ces problèmes, mais immobilise du capital, impose de gérer l’entretien matériel et peut laisser une machine sous-utilisée entre deux campagnes de test.

Après avoir validé votre première chaîne, vous pouvez consulter les offres de Mac distant de VPSNIX en comparant surtout la compatibilité Xcode, le Runtime requis, la méthode de récupération après redémarrage et la durée réelle d’utilisation. Pour une campagne ponctuelle, une commande de Mac distant peut être plus cohérente qu’un achat ; pour une suite XCTest ou UI exécutée chaque nuit, comparez plutôt une période de location suffisamment stable pour préserver vos résultats et vos procédures.

Le bon choix dépend donc de votre fréquence et de votre niveau d’autonomie : votre poste reste l’espace de création, tandis que le Mac distant devient un environnement de test vérifiable. Commencez par un Scheme, une destination et un paquet xcresult ; ne passez à une machine permanente qu’après avoir démontré que le projet sait se reconstruire, produire ses preuves et redémarrer sans surveillance constante.

Pour aller plus loin