Créer des tests reproductibles d’import de photos iOS avec simctl addmedia

DevOps et CI/CD ·~6 min de lecture

Créer des tests reproductibles d’import de photos iOS avec simctl addmedia

Après la sélection d’une image dans la photothèque, l’application peut devoir lire son orientation, générer une vignette, compresser le fichier d’origine, puis l’envoyer. Pour une vidéo, il faut également gérer la durée, le codec et la taille du fichier. Effectuer une seule sélection manuelle sur une machine de développement ne garantit pas que la prochaine build saura traiter le même jeu d’entrées. Une approche plus fiable consiste à versionner les fichiers multimédias comme fixtures de test, à réinitialiser un simulateur dédié sur un Mac distant, puis à les injecter dans la photothèque avec simctl addmedia.

Définir d’abord le périmètre à valider

Ces tests doivent porter sur l’interface entre l’application et la photothèque système, et non sur l’automatisation de l’application Photos. Il est recommandé de couvrir au minimum les quatre scénarios suivants :

  1. L’application détecte le nombre attendu d’images et de vidéos.
  2. Une fois le sélecteur refermé, le type de fichier, les dimensions en pixels et la durée des vidéos correspondent aux valeurs attendues.
  3. La tâche de compression ou d’envoi utilise la ressource d’origine, et non un aperçu récupéré par hasard.
  4. Les formats non pris en charge, les fichiers très volumineux et les changements d’autorisation déclenchent des erreurs clairement identifiées.

simctl addmedia permet de valider la chaîne de lecture et de traitement dans le simulateur, mais ne remplace pas les tests de capture avec la caméra, d’encodage propre aux appareils ni de pression réelle sur le stockage. En documentant explicitement ces limites dans le plan de test, on évite de confondre une restriction du simulateur avec un défaut du produit.

L’objectif d’un test de régression n’est pas d’injecter autant de fichiers que possible, mais d’associer chaque fichier à un comportement identifiable, reproductible et facile à diagnostiquer.

Préparer des fixtures multimédias petites et stables

Créez le répertoire Tests/Fixtures/Media dans le dépôt et n’y versionnez que les fichiers strictement nécessaires aux tests. Les noms doivent indiquer l’usage attendu, plutôt que de reprendre ceux générés automatiquement par un appareil photo.

Fichier Usage Assertion principale
portrait.jpg Image verticale contenant des données d’orientation Largeur et hauteur correctes après correction de l’orientation
transparent.png Image avec canal alpha Transparence conservée après l’export
short.mov Vidéo courte Durée et type de média corrects
invalid.txt Fichier non multimédia Rejet explicite lors de l’étape d’injection

Conservez également un manifeste SHA-256 afin d’éviter qu’un outil d’édition d’images ne réécrive involontairement les fixtures :

cd Tests/Fixtures/Media
shasum -a 256 portrait.jpg transparent.png short.mov > SHA256SUMS
shasum -a 256 -c SHA256SUMS

Ne réencodez pas les fixtures pendant l’exécution du job. Les encodeurs de différentes versions du système peuvent produire des métadonnées différentes, transformant un problème de « changement de comportement de l’application » en problème d’« entrée modifiée ». Si des fichiers dynamiques sont réellement nécessaires, consignez ensemble le script de génération, ses paramètres et les sommes de contrôle des fichiers produits.

Isoler un simulateur pour chaque job

Un simulateur partagé et utilisé sur une longue durée conserve des ressources dans la photothèque, des autorisations et des processus en arrière-plan. La méthode de référence la plus simple consiste à transmettre DEVICE_UDID depuis l’orchestrateur, puis à éteindre et effacer le simulateur avant d’attendre la fin de son démarrage :

set -euo pipefail

: "${DEVICE_UDID:?DEVICE_UDID is required}"
: "${BUNDLE_ID:?BUNDLE_ID is required}"

xcrun simctl shutdown "$DEVICE_UDID" 2>/dev/null || true
xcrun simctl erase "$DEVICE_UDID"
xcrun simctl boot "$DEVICE_UDID"
xcrun simctl bootstatus "$DEVICE_UDID" -b

xcrun simctl privacy "$DEVICE_UDID" reset photos "$BUNDLE_ID" || true
xcrun simctl privacy "$DEVICE_UDID" grant photos "$BUNDLE_ID"

Le modèle du simulateur et la version du système doivent également être fixés dans la configuration du job. Il ne suffit pas d’indiquer name=iPhone et de laisser Xcode choisir. Les jobs parallèles doivent utiliser des UDID distincts ; sinon, l’un d’eux peut exécuter erase pendant qu’un autre est encore en train de lancer ses tests.

Les tests d’autorisation doivent être répartis en deux groupes. Le scénario principal accorde à l’avance l’accès à la photothèque afin de valider le traitement des médias. Le scénario de refus exécute revoke séparément et vérifie uniquement le message affiché par l’application ainsi que le point d’accès permettant de rétablir l’autorisation. La réussite du test ne doit pas dépendre de l’apparition d’une boîte de dialogue système.

Injecter les fichiers et exécuter des tests ciblés

Avant l’injection, vérifiez les extensions et les sommes de contrôle, puis transmettez tous les fichiers pris en charge à addmedia en une seule commande :

FIXTURES="$PWD/Tests/Fixtures/Media"

shasum -a 256 -c "$FIXTURES/SHA256SUMS"

xcrun simctl addmedia "$DEVICE_UDID" \
  "$FIXTURES/portrait.jpg" \
  "$FIXTURES/transparent.png" \
  "$FIXTURES/short.mov"

xcodebuild test \
  -workspace Demo.xcworkspace \
  -scheme Demo \
  -destination "platform=iOS Simulator,id=$DEVICE_UDID" \
  -only-testing:MediaImportTests \
  -resultBundlePath "$PWD/Artifacts/MediaImport.xcresult"

Un retour réussi de addmedia indique uniquement que la commande a accepté les fichiers, pas que l’application voit déjà les bonnes ressources. Le code de test doit attendre que la requête sur la photothèque renvoie le nombre attendu, avec un délai maximal défini. Les assertions doivent porter en priorité sur le type de média, les dimensions en pixels, la plage de durée et le résultat métier produit. Évitez de dépendre de l’ordre d’affichage dans la photothèque système, car la date d’importation peut différer de la date de création des ressources.

Si l’application envoie des fichiers, remplacez la couche réseau par une implémentation locale de test qui enregistre le type MIME, le nombre d’octets et la somme de contrôle reçus. Vous pourrez ainsi confirmer que l’application lit bien la ressource d’origine, sans introduire les fluctuations d’un réseau externe dans les résultats de régression.

Conserver des échecs pouvant être analysés a posteriori

Un job en échec doit conserver au minimum trois catégories d’éléments : le fichier xcresult, les sommes de contrôle des fixtures et les informations sur l’appareil utilisé. Vous pouvez également afficher la liste des simulateurs disponibles, mais ne collectez pas le contenu de répertoires utilisateur sans rapport avec le problème.

Voici les erreurs d’interprétation les plus courantes et la manière de les traiter :

Arrêtez le simulateur à la fin du job. Si l’appareil a été créé temporairement par le job en cours, supprimez-le directement. Même les appareils persistants doivent être de nouveau soumis à erase avant le job suivant ; ne comptez pas sur la suppression individuelle des éléments de la photothèque. La liste de contrôle finale peut se résumer ainsi : sommes de contrôle des fixtures conformes, UDID réservé à un seul job, version du système fixe, état des autorisations explicite, attente possible du nombre d’éléments importés et archivage du bundle de résultats. Une fois ces conditions remplies, les échecs d’importation de médias reposent sur des entrées stables et laissent suffisamment d’éléments pour être analysés.

Questions fréquentes

simctl addmedia remplace-t-il les tests sur appareil réel ?

Non. Il couvre bien la découverte, la sélection et la lecture de médias dans le simulateur, mais la capture caméra, certains codecs et les contraintes matérielles exigent encore des tests sur appareil.

Comment éviter l’accumulation de médias entre deux tâches CI ?

Utilisez un simulateur dédié par tâche, arrêtez-le puis exécutez erase avant chaque injection. Détruisez ensuite l’appareil temporaire au lieu de partager une photothèque persistante.

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