Filmer les échecs des tests UI iOS sur un Mac dans le cloud

DevOps et CI/CD ·~6 min de lecture

Filmer les échecs des tests UI iOS sur un Mac dans le cloud

Filmer les échecs des tests UI iOS sur un Mac dans le cloud

Lorsqu’un test UI échoue sur un Mac dans le cloud, les assertions et les captures d’écran ne suffisent pas toujours. Une alerte qui apparaît puis disparaît aussitôt, une transition de page qui reste bloquée à mi-parcours ou un clavier qui masque un bouton ne peuvent être compris qu’en observant la séquence complète. La bonne approche ne consiste pas à conserver toutes les vidéos indéfiniment, mais à lancer l’enregistrement du simulateur concerné avant le test, à supprimer la vidéo en cas de succès et à l’archiver avec les journaux et le paquet de résultats uniquement en cas d’échec.

Fixer le périphérique de test et le périmètre de collecte

Ne transmettez pas directement booted à la commande d’enregistrement. Des tâches concurrentes, un périphérique laissé actif après une interruption anormale ou une session de débogage manuelle peuvent faire fonctionner plusieurs simulateurs en même temps. La vidéo risque alors de provenir du mauvais périphérique. Commencez par créer ou retrouver le périphérique réservé à la tâche, récupérez son UDID, puis utilisez-le pour le démarrage, les tests, l’enregistrement et le nettoyage.

DEVICE_NAME="CI-iPhone"
RUNTIME="com.apple.CoreSimulator.SimRuntime.iOS-18-0"
DEVICE_TYPE="com.apple.CoreSimulator.SimDeviceType.iPhone-16"

UDID="$(xcrun simctl list devices available -j |
  plutil -extract devices json -o - - |
  jq -r --arg name "$DEVICE_NAME" '
    .. | objects | select(.name? == $name) | .udid
  ' | head -n 1)"

if [ -z "$UDID" ]; then
  UDID="$(xcrun simctl create "$DEVICE_NAME" "$DEVICE_TYPE" "$RUNTIME")"
fi

xcrun simctl boot "$UDID" 2>/dev/null || true
xcrun simctl bootstatus "$UDID" -b

L’identifiant du runtime dépend des versions de Xcode installées. Le pipeline doit donc le vérifier avec xcrun simctl list runtimes avant l’exécution, au lieu de supposer que toutes les machines disposent de la même version. Lorsque plusieurs tâches s’exécutent en parallèle, le nom du périphérique doit également inclure l’identifiant de la tâche afin d’éviter tout partage d’état.

L’enregistrement sert à compléter la chronologie d’un échec, pas à remplacer les journaux. La vidéo répond à la question « que s’est-il d’abord passé dans l’interface ? », tandis que les journaux et le xcresult indiquent « qu’a enregistré le framework de test ? ».

Arrêter proprement le processus d’enregistrement

simctl io recordVideo s’exécute en continu : le script doit donc conserver son PID. À la fin du test, n’envoyez pas immédiatement un signal d’arrêt forcé. Envoyez d’abord INT afin que l’outil termine l’écriture de l’index du conteneur vidéo, puis attendez la fin du processus.

ARTIFACTS="${PWD}/artifacts"
VIDEO="${ARTIFACTS}/ui-test.mp4"
RESULT="${ARTIFACTS}/UITests.xcresult"
LOG="${ARTIFACTS}/xcodebuild.log"

mkdir -p "$ARTIFACTS"
rm -rf "$RESULT"
rm -f "$VIDEO" "$LOG"

xcrun simctl io "$UDID" recordVideo \
  --codec=h264 \
  --force "$VIDEO" &
RECORDER_PID=$!

finish_recording() {
  if kill -0 "$RECORDER_PID" 2>/dev/null; then
    kill -INT "$RECORDER_PID"
    wait "$RECORDER_PID" || true
  fi
}

trap finish_recording EXIT INT TERM

H.264 est généralement pratique pour prévisualiser la vidéo dans un navigateur ou en pièce jointe d’un ticket. Si l’équipe doit ensuite effectuer une analyse image par image, un autre codec peut être utilisé après avoir vérifié sa compatibilité avec le système de gestion des artefacts. Évitez toutefois de mélanger les formats dans un même pipeline, sous peine de rendre les outils de lecture et les règles de conservation imprévisibles.

Préserver le véritable code de sortie du test

L’enregistrement est un processus auxiliaire et ne doit pas masquer le résultat de xcodebuild. La méthode la plus fiable consiste à désactiver temporairement l’arrêt en cas d’erreur, à enregistrer séparément le code de sortie du test, puis à terminer normalement l’enregistrement. Si tee est également utilisé pour afficher le journal, il faut récupérer l’état de sortie de xcodebuild dans le pipeline, et non interpréter à tort le succès de tee comme celui du test.

set +e
xcodebuild test \
  -workspace App.xcworkspace \
  -scheme AppUITests \
  -destination "platform=iOS Simulator,id=${UDID}" \
  -resultBundlePath "$RESULT" \
  >"$LOG" 2>&1
TEST_STATUS=$?
set -e

finish_recording
trap - EXIT INT TERM

if [ "$TEST_STATUS" -eq 0 ]; then
  rm -f "$VIDEO"
  exit 0
fi

exit "$TEST_STATUS"

Le script ne s’arrête volontairement pas dès l’échec du test, car l’enregistrement doit encore être finalisé. resultBundlePath doit pointer vers un chemin propre à chaque tâche, et l’ancien répertoire doit être supprimé avant l’exécution. Sinon, des résultats précédents risquent d’être mélangés à l’échec en cours.

Valider la vidéo au lieu de vérifier seulement sa présence

Un fichier vide, un fichier très court qui ne contient que l’en-tête du conteneur ou un enregistrement interrompu de force n’a aucune valeur diagnostique. Avant l’archivage, vérifiez au minimum la taille du fichier et utilisez les outils multimédias du système pour lire sa durée. Une vidéo très courte reste normale lorsque le test échoue immédiatement après son lancement ; le seuil de durée ne doit donc pas être trop élevé.

Vérification Action recommandée Traitement en cas d’échec
Présence du fichier test -f Conserver le journal et signaler l’absence de l’enregistrement
Fichier non vide test -s Vérifier le PID de l’enregistreur et l’espace disque
Durée lisible Interroger les métadonnées multimédias Considérer le fichier comme endommagé et ne pas téléverser un conteneur vide
Périphérique correct Comparer l’UDID enregistré Arrêter la tâche et nettoyer le mauvais périphérique
Paquet de résultats du test Vérifier le répertoire xcresult Conserver le journal brut comme solution de secours

L’UDID, l’heure de début du test et le chemin de la vidéo peuvent être consignés dans un simple fichier texte archivé avec la vidéo. N’y inscrivez pas d’identifiants d’accès, l’ensemble des variables d’environnement ni des lignes de commande non expurgées. La vidéo elle-même peut aussi afficher des notifications, des noms de comptes de test ou des données métier. Les jeux de données de test doivent donc reposer sur des échantillons dédiés et non sensibles.

Gérer la concurrence, les délais d’expiration et les processus résiduels

Chaque tâche doit disposer de son propre simulateur, de son propre répertoire de résultats et de son propre nom de fichier vidéo. Le partage de booted, d’un chemin fixe comme artifacts/ui-test.mp4 ou d’un répertoire DerivedData commun permettrait à des tâches concurrentes d’écraser leurs fichiers respectifs. Le répertoire de la tâche peut être généré à partir de l’identifiant unique fourni par le pipeline, puis les fichiers temporaires des tâches réussies peuvent être supprimés à la sortie.

Lorsqu’un mécanisme de délai d’expiration externe interrompt le test, la fonction de nettoyage doit tout de même pouvoir s’exécuter. Envoyez d’abord au processus de test un signal d’arrêt qu’il peut traiter, laissez quelques secondes à trap pour finaliser l’enregistrement, puis seulement ensuite procédez au nettoyage forcé. Avant la tâche suivante, il est possible de rechercher les processus d’enregistrement simctl io dont le processus parent s’est déjà terminé. N’utilisez toutefois pas un killall trop général, car il pourrait interrompre d’autres tâches exécutées sur la même machine.

Un ensemble d’artefacts fiable ne contient généralement que trois éléments : la vidéo de l’échec, le paquet de résultats xcresult et le journal de compilation brut. Tous trois doivent porter le même identifiant de tâche et suivre la même durée de conservation. Depuis la liste des échecs, il devient alors possible d’ouvrir une exécution, de regarder d’abord la vidéo pour identifier l’état de l’interface, d’utiliser ensuite le paquet de résultats pour retrouver les assertions et les pièces jointes, puis de consulter le journal afin de vérifier la commande, le périphérique cible et le code de sortie. On obtient ainsi une chaîne de preuves complète, sans collecte excessive.

Questions fréquentes

Pourquoi éviter la cible booted avec simctl ?

Plusieurs simulateurs peuvent être démarrés en parallèle. Un UDID explicite garantit que le test, la capture vidéo et le nettoyage concernent le même appareil.

Pourquoi certaines vidéos sont-elles illisibles après le test ?

Un arrêt forcé peut interrompre l’écriture de l’index du conteneur. Envoyez le signal INT au processus d’enregistrement, puis attendez sa fin avant l’archivage.

Faut-il conserver les vidéos des tests réussis ?

Non dans la plupart des pipelines. Supprimez-les après un succès et archivez la vidéo, le journal et le xcresult uniquement en cas d’échec.

Debug M4

Lancez votre prochaine compilation sur un nœud physique Apple Silicon dédié

Choisissez la durée de location et la région du nœud, vérifiez le Mac Mini M4, les 16 Go de RAM, le SSD de 256 Go et le montant en USD, puis envoyez votre commande.

Louer un Mac cloud maintenant