Après la fusion d’une refonte de l’écran d’accueil, tous les tests fonctionnels sont passés, mais les utilisateurs ont commencé à signaler un premier lancement plus lent. Les performances au démarrage passent facilement inaperçues au quotidien : une nouvelle migration de base de données, la lecture synchrone d’une configuration, l’initialisation du module d’analyse ou le chargement d’une grande image peuvent discrètement alourdir le thread principal. Plutôt que d’attendre qu’un test manuel révèle le problème, mieux vaut transformer la mesure du démarrage à froid sur un Mac cloud fixe en contrôle obligatoire avant toute fusion.
Commencer par définir un scénario de démarrage comparable
« Ouvrir l’application » ne constitue pas une définition de test complète. Il faut au minimum fixer la configuration de compilation, le modèle de Simulator, la version du runtime, les données initiales de l’application et les arguments de lancement. L’objectif du test doit également rester unique : mesurer, par exemple, uniquement le délai entre la création du processus et l’apparition du premier écran interactif, sans inclure la requête de connexion ni le téléchargement de données de test.
Il est recommandé de créer un plan Performance.xctestplan distinct, de n’y activer que les tests de performances au démarrage et de désactiver l’exécution aléatoire. L’environnement de test utilise des arguments de lancement pour atteindre un écran stable :
final class LaunchPerformanceTests: XCTestCase {
override func setUp() {
continueAfterFailure = false
}
func testColdLaunch() {
let app = XCUIApplication()
app.launchArguments = ["-uiTesting", "-resetLocalState"]
let options = XCTMeasureOptions()
options.iterationCount = 8
measure(
metrics: [XCTApplicationLaunchMetric(waitUntilResponsive: true)],
options: options
) {
app.launch()
}
}
}
L’argument -resetLocalState doit être traité par le point d’entrée de test de l’application et ne supprimer que l’état local pouvant être recréé. Ne l’utilisez pas dans le chemin d’exécution de production pour ignorer une initialisation qui doit réellement être mesurée. Vous n’obtiendriez alors que la « vitesse de démarrage propre aux tests ».
Fixer l’état du Mac cloud et de Simulator
Un garde-fou de performances exige une machine physique dédiée, et non un environnement partagé dans lequel des tâches inconnues se disputent le CPU et le disque. Avant chaque exécution, vérifiez le chemin Xcode actif, les appareils Simulator disponibles et l’espace disque restant :
set -euo pipefail
xcode-select -p
xcodebuild -version
xcrun simctl list devices available
df -h "$HOME"
Sélectionnez dans le plan de test un Simulator déjà installé. Ne laissez pas le script choisir automatiquement « le premier appareil disponible », car toute modification des images rendrait les données historiques incomparables. Pendant l’exécution du garde-fou, évitez également les archivages parallèles, les mises à jour de dépendances et les tâches d’indexation à grande échelle.
Les données de performances décrivent d’abord l’environnement, puis seulement le code. Une mesure dont on ne peut préciser le nœud d’exécution, la configuration de compilation et l’état de Simulator ne doit pas servir directement à bloquer une fusion.
Lors de la création initiale de la référence, répétez le test sur le même commit. Si la dispersion des résultats est manifestement trop importante, examinez d’abord les tâches en arrière-plan, la pression exercée sur le disque et la logique de réinitialisation des données de test, au lieu d’assouplir immédiatement les seuils.
Exécuter un garde-fou unique avec xcodebuild
La tâche en ligne de commande ne doit exécuter que le test ciblé et doit conserver le paquet de résultats comme artefact du pipeline. Le nom de l’appareil doit être remplacé par le modèle réellement fixé dans le plan de test :
set -o pipefail
mkdir -p Artifacts
xcodebuild test \
-workspace App.xcworkspace \
-scheme App \
-testPlan Performance \
-destination 'platform=iOS Simulator,name=iPhone 16' \
-only-testing:AppUITests/LaunchPerformanceTests/testColdLaunch \
-resultBundlePath Artifacts/Launch.xcresult \
| tee Artifacts/launch-test.log
La commande set -o pipefail est essentielle. Sans elle, si xcodebuild échoue, la commande tee située en fin de pipeline peut tout de même faire apparaître la tâche comme réussie. Conservez à la fois Launch.xcresult et le journal texte : le premier permet de consulter chaque mesure et les pièces jointes du test, tandis que le second facilite l’identification rapide des erreurs de compilation ou de lancement.
| Élément contrôlé | Méthode de fixation | Traitement après modification |
|---|---|---|
| Xcode | Enregistrer xcodebuild -version |
Recréer d’abord une référence candidate |
| Simulator | Fixer le modèle et le runtime | Ne pas comparer directement avec l’ancienne référence |
| Configuration de compilation | Utiliser le même plan de test | Refuser toute substitution temporaire de paramètres |
| Données de test | Effectuer une réinitialisation déterministe avec les arguments de lancement | Vérifier que la réinitialisation est complète |
| Nombre d’itérations | Toujours utiliser 8 exécutions pour le garde-fou | Ne pas statuer sur un seul résultat |
Gérer une référence plutôt que poursuivre une mesure isolée
Dans le rapport de test Xcode, créez une référence de performances pour le test concerné et placez les fichiers de référence partagés générés sous contrôle de version. Toute modification de cette référence doit être examinée comme un fichier de verrouillage des dépendances : la description du commit doit préciser l’origine du changement, le commit de validation et l’impact attendu, et ne peut pas se limiter à « mise à jour des données de performances ».
Les seuils doivent distinguer les avertissements des blocages. Les faibles variations peuvent être conservées pour observer la tendance, tandis qu’un écart qui dépasse toujours la plage de tolérance après plusieurs nouvelles exécutions doit provoquer un échec. La décision ne repose pas sur le meilleur résultat isolé, mais sur la présence d’un écart stable par rapport à la référence approuvée après plusieurs itérations dans le même environnement.
La référence ne doit pas être mise à jour directement dans les situations suivantes :
- le nœud de test exécutait simultanément d’autres tâches gourmandes en ressources ;
- le modèle ou le runtime de Simulator a changé ;
- le premier téléchargement des dépendances ou l’indexation n’est pas terminé ;
- des étapes d’initialisation ont été ignorées pour faire passer le test ;
- une seule exécution présente une anomalie, tandis que les autres résultats sont normaux.
Conserver les preuves après un échec et localiser le chemin responsable
En cas d’échec du garde-fou, relancez d’abord le test sur le même Mac cloud et le même commit. Si le résultat est reproductible, décomposez le démarrage en plusieurs étapes : point d’entrée du processus, injection des dépendances, ouverture de la base de données, construction du modèle du premier écran, décodage des ressources et rendu de la première image. Vous pouvez ajouter des événements os_signpost uniformes à ces limites afin que l’analyse indique précisément où le temps est consommé, au lieu de déduire la cause à partir de l’ampleur du commit.
Commencez l’analyse par les changements les plus récents, sans vous limiter au code métier. Les modifications de la configuration de compilation, les options de diagnostic du débogage, l’augmentation du volume des ressources et les fixtures de test peuvent également modifier le chemin de démarrage. Après correction, conservez les deux fichiers xcresult, celui de l’échec et celui de la réussite, puis consignez les commits comparés dans la demande de fusion.
La valeur d’un garde-fou fiable ne consiste pas à attribuer une étiquette absolue au temps de démarrage, mais à maintenir la comparabilité d’un même scénario dans la durée. En fixant l’environnement, en versionnant la référence, en conservant les preuves et en soumettant les mises à jour de cette référence à une revue, les performances au démarrage cessent d’être une impression subjective pour devenir une contrainte d’ingénierie traçable.
Questions fréquentes
Combien d’itérations faut-il exécuter pour mesurer le démarrage ?
Exécutez au moins 5 mesures sur le même commit et plutôt 8 ou davantage dans le contrôle, en conservant le même Simulator, le même runtime, la même configuration et les mêmes processus de fond.
Faut-il relever le seuil dès que le contrôle échoue ?
Non. Relancez d’abord le test sur le même nœud et vérifiez l’état du Simulator ainsi que le chemin exécuté. Ne remplacez la référence qu’après validation d’un changement volontaire du produit.
Reproduisez vos workflows sur un Mac cloud que vous activez et arrêtez selon vos projets
Choisissez la ressource adaptée parmi trois configurations Apple Silicon et louez-la à la journée, à la semaine, au mois ou au trimestre. Chaque appareil est une machine physique dédiée, et non une machine virtuelle ; sa disponibilité réelle est indiquée en temps réel dans la console.