Aller au contenu principal

Capture d'écran

Capturez des screenshots App Store directement depuis les simulateurs iOS/iPadOS via des tests UI. Remplace fastlane snapshot.

Démarrage rapide​

ascelerate screenshot init                  # Create config and helper in ascelerate/
ascelerate screenshot # Capture screenshots

Configuration avec un agent de codage IA​

La capture demande une cible de tests UI, le helper de capture, un mode capture avec du contenu de démonstration dans l'app, les tests eux-mêmes et la configuration. Un agent de codage peut mettre tout cela en place :

ascelerate screenshot setup-prompt          # Print the setup instructions
ascelerate screenshot setup-prompt --copy # Copy them to the clipboard

Collez les instructions dans un agent de codage qui travaille dans le projet (Claude Code, Codex, Cursor, l'assistant de codage de Xcode…). Elles partent de ce que le projet contient déjà (projets, schemes, cibles de tests UI, localisations, configuration, version du helper, simulateurs installés) : relancer la commande montre donc ce qu'il reste à faire. Elles couvrent aussi les contours d'appareil, que vous téléchargez vous-même depuis les ressources de design d'Apple (Product Bezels).

--design affiche à la place les instructions d'un générateur de designs : une petite application web dans app-store-screenshots/ qui transforme les captures encadrées en images App Store avec des titres dans chaque langue, exportées pour ascelerate apps media upload (voir Médias).

Commandes​

Exécuter​

ascelerate screenshot                       # Capture screenshots
ascelerate screenshot run # Same as above
ascelerate screenshot --json-events # Progress as JSON Lines events on stdout

Utilise toujours ascelerate/screenshot.yml dans le répertoire courant.

--json-events sert aux outils qui suivent une exécution : stdout contient un objet JSON par ligne (start, build, language, device avec des étapes comme testing, passed, failed et collected, et finished avec tous les résultats), et la progression lisible passe sur stderr.

Initialiser​

ascelerate screenshot init

Crée ascelerate/screenshot.yml et ascelerate/ScreenshotHelper.swift dans le répertoire ascelerate/. Demande confirmation avant l'écriture (-y l'évite). Ne remplace pas les fichiers existants.

Créer le helper​

ascelerate screenshot create-helper         # Generates ScreenshotHelper.swift
ascelerate screenshot create-helper -o CustomHelper.swift
ascelerate screenshot create-helper -o UITests/ScreenshotHelper.swift -y # Overwrite without asking

Encadrement​

ascelerate screenshot frame                    # Frame screenshots with device bezels

Encadre les captures d'écran avec des contours d'appareil. Utilise les paramètres frameDevice et deviceBezel de la configuration. Peut être exécuté indépendamment après la capture.

Diagnostic​

ascelerate screenshot doctor                   # Check config and environment
ascelerate screenshot doctor --json # The same as JSON

Vérifie la configuration et l'environnement : fichier de configuration, existence du projet/workspace, disponibilité de xcodebuild et simctl, simulateurs, version du fichier helper, fichiers de contour d'appareil et répertoires de sortie. Affiche une liste de contrôle avec des indicateurs de réussite/échec/avertissement. Avec --json, il affiche la configuration (scheme, appareils, langues, répertoire de sortie) et chaque vérification avec son statut (pass, warn ou fail).

Configuration (ascelerate/screenshot.yml)​

workspace: MyApp.xcworkspace
# project: MyApp.xcodeproj # Use project instead of workspace
scheme: AppUITests
devices:
- simulator: iPhone 17 Pro Max
# frameDevice: true
# deviceBezel: ./bezels/iPhone 17 Pro Max.png
- simulator: iPad Pro 13-inch (M5)
# frameDevice: true
# deviceBezel: ./bezels/iPad Pro 13-inch (M5).png
languages:
- en-US
- de-DE
outputDirectory: ./screenshots
# framedOutputDirectory: ./screenshots/framed
clearPreviousScreenshots: true
eraseSimulator: false
localizeSimulator: true
overrideStatusBar: true
darkMode: false
disableAnimations: true
waitAfterBoot: 0
# waitAfterEraseAndReboot: 30 # Attente supplémentaire pour les alertes système de premier lancement
# statusBarArguments: "--time '9:41' --dataNetwork wifi"
# testWithoutBuilding: true # Skip build, use existing xctestrun
# cleanBuild: false
# headless: false # Don't open simulator windows (DeviceHub / Simulator.app)
# helperPath: AppUITests/ScreenshotHelper.swift
# launchArguments:
# - -ui_testing
# configuration: Debug # Build configuration
# testplan: MyTestPlan # Xcode test plan name
# numberOfRetries: 0 # Retry failed languages (erase + reboot simulator)
# stopAfterFirstError: false # Stop all devices on first failure
# reinstallApp: false # Delete and reinstall app before tests
# disableAssetDownloads: false # Désactiver mobileassetd (aucun téléchargement d'assets Siri/clavier/ML ; bloque aussi les assets ML sur l'appareil)
# xcargs: SWIFT_ACTIVE_COMPILATION_CONDITIONS=SCREENSHOTS

Utilisation dans les UITests​

Ajoutez ScreenshotHelper.swift à votre cible UITest :

override func setUp() {
setupScreenshots(app)
app.launch()
}

func testScreenshots() {
screenshot("01-home")
app.buttons["Settings"].tap()
screenshot("02-settings")
}

Votre application peut détecter le mode screenshot :

if ProcessInfo.processInfo.arguments.contains("-ASC_SCREENSHOT") {
// Show demo data, hide debug UI, etc.
}

Le helper fournit également disableAnimationsIfNeeded() pour désactiver les animations lorsque disableAnimations est activé dans la configuration :

override func setUp() {
setupScreenshots(app)
disableAnimationsIfNeeded()
app.launch()
}

iPhone Duo​

Sur le simulateur iPhone Duo (Xcode 27.1+), setHinge(.open) déplie l'appareil et setHinge(.closed) le replie. Le helper attend ensuite que le système déplace l'application vers l'écran correspondant, afin que le prochain appel à screenshot() capture cet écran. Le simulateur démarre toujours replié.

func testScreenshots() {
screenshot("01-folded")
setHinge(.open)
screenshot("02-unfolded")
}

Déplié, de nombreuses applications adoptent la même disposition que sur iPad, mais UIDevice.current.userInterfaceIdiom renvoie toujours .phone dans le test runner. Pour adapter le comportement de vos tests, vérifiez plutôt ProcessInfo.processInfo.environment["SIMULATOR_MODEL_IDENTIFIER"] == "iPhone19,4".

attention

Il n'existe pas d'API officielle pour la charnière. Le helper envoie le même événement d'entrée que le curseur de charnière de Device Hub ; une future version de Xcode pourrait donc le rendre inopérant.

Fonctionnement​

  1. Build unique avec build-for-testing (ou ignoré si testWithoutBuilding: true)
  2. Pour chaque langue : démarre tous les simulateurs, neutralise la bannière iOS 26 « Prêt pour Apple Intelligence » (et mobileassetd si disableAssetDownloads est défini), localise, remplace la barre d'état
  3. Exécute les tests en parallèle sur tous les appareils
  4. Si numberOfRetries est défini et qu'un appareil échoue : réinitialise les simulateurs en échec, re-localise, redémarre et relance les tests
  5. Collecte les screenshots du cache par appareil vers le répertoire de sortie
  6. Encadre les captures d'écran avec des contours d'appareil (si frameDevice est activé)
  7. Les erreurs sont ignorées et le processus continue — les logs d'erreur sont enregistrés dans la sortie

Sortie​

screenshots/
├── en-US/
│ ├── iPhone 17 Pro Max-01-home.png
│ ├── iPhone 17 Pro Max-02-settings.png
│ └── iPad Pro 13-inch (M5)-01-home.png
└── de-DE/
└── ...

Encadrement d'appareil​

Encadrez les captures d'écran avec les contours d'appareils Apple.

info

Les contours d'appareils ne sont pas inclus avec ascelerate — téléchargez-les depuis Apple Product Bezels (compte Apple Developer requis). Le téléchargement est un fichier DMG contenant les contours PNG pour tous les appareils actuels.

Configuration​

  1. Téléchargez le DMG Product Bezels depuis Apple Design Resources
  2. Extrayez les fichiers PNG de contour dans un dossier de votre projet (ex. ./bezels/)
  3. Activez l'encadrement par appareil dans la configuration :
devices:
- simulator: iPhone 17 Pro Max
frameDevice: true
deviceBezel: ./bezels/iPhone 17 Pro Max.png
- simulator: iPad Pro 13-inch (M5)
frameDevice: false

Un appareil peut déclarer plusieurs contours. Chaque capture d'écran est encadrée avec le contour dont la zone d'écran correspond à sa taille. Ainsi, les captures repliées d'un iPhone Duo reçoivent le contour fermé, et les captures dépliées le contour ouvert :

devices:
- simulator: iPhone Duo
frameDevice: true
deviceBezel:
- ./bezels/iPhone Duo - Outer Closed Portrait.png
- ./bezels/iPhone Duo - Inner Open Landscape.png

Les captures en paysage utilisent un contour paysage s'il figure dans la liste, sinon le contour portrait pivoté.

Sortie​

Les captures d'écran encadrées sont enregistrées dans framedOutputDirectory (par défaut : {outputDirectory}/framed) :

screenshots/framed/
├── en-US/
│ └── iPhone 17 Pro Max-01-home.png
└── de-DE/
└── ...

Seuls les appareils avec frameDevice: true sont encadrés. L'encadrement s'exécute automatiquement après chaque langue pendant screenshot run, ou de manière autonome via screenshot frame.

Options​

OptionDescription
clearPreviousScreenshotsVider le dossier de langue avant la collecte (uniquement si tous les appareils réussissent)
eraseSimulatorRéinitialiser le simulateur avant chaque langue
localizeSimulatorDéfinir la langue/locale du simulateur par langue
overrideStatusBarRemplacer la barre d'état (9:41, barres pleines, Wi-Fi)
statusBarArgumentsArguments personnalisés pour xcrun simctl status_bar
darkModeActiver le mode sombre sur les simulateurs
disableAnimationsDésactiver les animations pendant les tests
waitAfterBootSecondes d'attente après le démarrage du simulateur (défaut : 0)
waitAfterEraseAndRebootSecondes d'attente supplémentaires lorsque le simulateur est dans un état neuf — première langue de l'exécution, ou chaque fois que le simulateur a été effacé (via eraseSimulator: true ou un nouvel essai). Donne aux alertes système de premier lancement le temps d'apparaître avant les captures d'écran. (La bannière iOS 26 « Prêt pour Apple Intelligence » est neutralisée automatiquement et ne nécessite aucune attente.)
testWithoutBuildingIgnorer le build, utiliser le fichier xctestrun existant
cleanBuildExécuter clean avant le build
headlessNe pas ouvrir les fenêtres du simulateur (DeviceHub depuis Xcode 27, Simulator.app avant)
helperPathChemin vers ScreenshotHelper.swift pour la vérification de version
launchArgumentsArguments de lancement supplémentaires passés à l'application
configurationConfiguration de build (ex. Debug, Release)
testplanNom du plan de test Xcode
numberOfRetriesNombre de tentatives pour les langues échouées — réinitialise le simulateur, re-localise, redémarre et relance les tests. Seuls les appareils en échec sont relancés. Les résultats relancés sont marqués dans le tableau récapitulatif.
stopAfterFirstErrorArrêter tous les appareils après le premier échec
reinstallAppSupprimer et réinstaller l'application avant les tests
disableAssetDownloadsDésactive mobileassetd dans le simulateur pour qu'il cesse de télécharger des gigaoctets d'assets Siri, clavier et ML dans les simulateurs fraîchement effacés. Bloque aussi les assets ML sur l'appareil dont certaines apps ont besoin (ex. reconnaissance de texte) ; laissez-le désactivé si vos captures en dépendent. Appliqué à chaque préparation, car un effacement le réinitialise.
xcargsArguments supplémentaires passés à xcodebuild
frameDeviceActiver l'encadrement pour cet appareil (par appareil)
deviceBezelChemin vers le fichier PNG de contour d'appareil, ou liste de chemins ; chaque capture utilise le contour adapté à sa taille (par appareil)
framedOutputDirectoryRépertoire de sortie pour les captures encadrées (défaut : {outputDirectory}/framed)