Automatiser vos captures d’écran avec fastlane snapshot et frameit
Configurez fastlane snapshot, screengrab et frameit pour capturer, encadrer et publier vos captures d’écran depuis la CI, et voyez quand ça vaut le coup.
fastlane automatise les captures d’écran pour les stores en trois étapes. snapshot (iOS) et screengrab (Android) exécutent vos tests d’interface sur des simulateurs ou des émulateurs, dans chaque langue que vous listez, et enregistrent une capture à chaque endroit que vous marquez. frameit les entoure d’un cadre d’appareil, d’un fond et d’un titre. deliver et supply envoient le résultat sur App Store Connect et Google Play. Une fois tout en place, régénérer toutes les captures ne demande qu’une commande.
Cette dernière phrase résume tout l’intérêt, et la configuration résume tout le coût. Ce guide passe en revue chaque brique avec une config qui fonctionne, puis donne un avis honnête sur les cas où ça vaut le coup.
- fastlane snapshot exécute les tests d’interface Xcode sur les appareils et dans les langues d’un Snapfile, et prend une capture à chaque endroit où un test appelle snapshot("name").
- screengrab est l’équivalent Android : il exécute des tests d’instrumentation, et Screengrab.screenshot("name") enregistre chaque écran dans fastlane/metadata/android.
- frameit ajoute cadres d’appareil, fond et titres à partir d’un Framefile.json et de fichiers title.strings par langue ; il a besoin d’ImageMagick.
- Les cadres de frameit sont en retard sur le matériel : en octobre 2026, son dépôt de cadres s’arrêtait à la gamme iPhone 17, à l’iPad Pro 12,9 pouces (4e génération) et au Pixel 5.
- L’automatisation est rentable pour les apps qui publient souvent dans plusieurs langues ; pour une seule langue et des mises à jour rares, capturer à la main est généralement plus rapide.
Comment fonctionne fastlane snapshot
fastlane snapshot s’appuie sur les tests d’interface de Xcode. Vous écrivez un test d’interface qui parcourt votre app ; à chaque écran qui mérite d’être montré, il appelle snapshot("01Home"). snapshot exécute ce test une fois par combinaison d’appareil et de langue, et rassemble les images dans fastlane/screenshots/<language>/.
Installation
- Ajoutez une cible UI Test à votre projet Xcode si vous n’en avez pas.
- Lancez
fastlane snapshot initdans le dossier du projet. La commande crée unSnapfileet unSnapshotHelper.swift. - Ajoutez
SnapshotHelper.swiftà la cible UI Test.
Le test d’interface
import XCTest
final class ScreenshotTests: XCTestCase {
override func setUp() {
continueAfterFailure = false
let app = XCUIApplication()
setupSnapshot(app)
app.launchArguments += ["-demoData"]
app.launch()
}
func testStoreScreenshots() {
let app = XCUIApplication()
snapshot("01Home")
app.tabBars.buttons["Budget"].tap()
snapshot("02Budget")
app.buttons["Add expense"].tap()
snapshot("03AddExpense")
}
}setupSnapshot(app) transmet la langue et la région en cours à l’app, et c’est comme ça qu’un seul test produit toutes les séries localisées. L’argument -demoData est une convention à nous : l’app le détecte dans les builds de debug et charge du contenu d’exemple, pour qu’aucune capture ne montre un écran vide. Préfixer les noms par des numéros garde les fichiers dans l’ordre d’envoi.
Le Snapfile
# fastlane/Snapfile
devices([
"iPhone 17 Pro Max",
"iPad Pro 13-inch (M5)"
])
languages([
"en-US",
"de-DE",
"ja"
])
scheme("MyAppUITests")
output_directory("./fastlane/screenshots")
clear_previous_screenshots(true)
override_status_bar(true) # 9:41, full battery, full reception
dark_mode(false)
launch_arguments(["-demoData"])Les noms d’appareils doivent correspondre aux simulateurs installés dans votre Xcode ; xcrun simctl list devicetypes les affiche. Un simulateur iPhone 17 Pro Max capture en 1320 × 2868, l’une des tailles qu’App Store Connect accepte pour son plus grand emplacement iPhone. Lancez ensuite :
fastlane snapshotD’autres options de snapshot à connaître : localize_simulator règle aussi la langue système du simulateur, erase_simulator repart d’un appareil vierge à chaque exécution, reinstall_app désinstalle l’app au préalable, et override_status_bar_arguments accepte vos propres options simctl status_bar. Si vous voulez savoir ce que font ces options, notre guide des captures propres sur simulateur et émulateur les détaille, ainsi que les commandes manuelles que snapshot automatise.
screengrab : l’équivalent Android
screengrab fait le même travail avec les tests d’instrumentation Android. Ajoutez la bibliothèque à vos dépendances de test :
// app/build.gradle
androidTestImplementation 'tools.fastlane:screengrab:x.x.x'Vérifiez que src/debug/AndroidManifest.xml inclut les autorisations listées dans la doc (comme DISABLE_KEYGUARD), puis écrivez le test :
@RunWith(AndroidJUnit4.class)
public class ScreenshotTest {
@ClassRule
public static final LocaleTestRule localeTestRule = new LocaleTestRule();
@BeforeClass
public static void beforeAll() {
CleanStatusBar.enableWithDefaults();
}
@AfterClass
public static void afterAll() {
CleanStatusBar.disable();
}
@Rule
public ActivityScenarioRule<MainActivity> rule =
new ActivityScenarioRule<>(MainActivity.class);
@Test
public void storeScreenshots() {
Screengrab.screenshot("01_home");
onView(withId(R.id.nav_budget)).perform(click());
Screengrab.screenshot("02_budget");
}
}LocaleTestRule change de langue à chaque exécution, et CleanStatusBar est une surcouche du mode démo de l’interface système d’Android ; la doc précise qu’il faut l’API 23 ou plus. Compilez les APK, générez un Screengrabfile, puis lancez-le :
./gradlew assembleDebug assembleAndroidTest
fastlane screengrab init # creates the Screengrabfile
fastlane screengrab# fastlane/Screengrabfile
app_package_name("com.example.app")
app_apk_path("app/build/outputs/apk/debug/app-debug.apk")
tests_apk_path("app/build/outputs/apk/androidTest/debug/app-debug-androidTest.apk")
locales(["en-US", "de-DE", "ja-JP"])
clear_previous_screenshots(true)Par défaut, les captures vont dans fastlane/metadata/android/<locale>/images/phoneScreenshots, c’est-à-dire exactement là où supply va les chercher. Un point à vérifier sur Android : Google Play refuse les captures dont le grand côté dépasse le double du petit, donc choisissez un profil d’émulateur qui ne soit pas plus allongé que 2:1.
frameit : cadres d’appareil et titres
frameit prend les captures brutes et les place dans des cadres d’appareil. Il a besoin d’ImageMagick (brew install imagemagick). Les cadres se téléchargent automatiquement au premier lancement.
fastlane frameit # iOS and Mac screenshots
fastlane frameit android # Android screenshots
fastlane frameit silver # silver frame variantsUn cadre d’appareil seul ne rend pas automatiquement l’image prête pour l’App Store : l’image encadrée peut ne correspondre à aucune taille acceptée par App Store Connect. La doc de fastlane indique que pour l’App Store, il vous faut un Framefile.json avec titres et fond, qui produit à la place une image marketing complète.
Framefile.json
Placez-le dans le dossier screenshots :
{
"device_frame_version": "latest",
"default": {
"title": {
"font": "./fonts/Inter-Bold.ttf",
"font_size": 110,
"color": "#0F172A"
},
"keyword": {
"font": "./fonts/Inter-Bold.ttf",
"color": "#F97316"
},
"background": "./background.jpg",
"padding": 50,
"show_complete_frame": false,
"title_below_image": false
},
"data": [
{ "filter": "01Home" },
{ "filter": "02Budget", "keyword": { "color": "#3B82F6" } },
{ "filter": "03AddExpense" }
]
}Chaque entrée de data s’applique aux captures dont le nom de fichier contient son filter, et peut remplacer les valeurs par défaut. Le texte lui-même se trouve dans des fichiers par langue, title.strings et éventuellement keyword.strings, dans chaque dossier de langue :
"01Home" = "See every euro, every month";
"02Budget" = "Budgets that adjust themselves";
"03AddExpense" = "Log a purchase in two taps";Cette ligne vide au début est volontaire : la doc indique que le fichier doit commencer par une ligne vide, et être encodé en UTF-8 ou en UTF-16 BE avec BOM. Elle précise aussi qu’il faut fournir un fond si vous voulez des titres. Si les titres n’apparaissent pas, vérifiez d’abord ces trois points.
Les cadres d’appareil de frameit sont en retard sur le matériel
Les cadres de frameit proviennent du dépôt séparé frameit-frames, et ils sont ajoutés après la sortie des appareils. Quand nous avons regardé en octobre 2026 :
| Gamme | Cadre le plus récent du dépôt | Pas encore disponible |
|---|---|---|
| iPhone | iPhone 17, 17 Pro, 17 Pro Max | Modèles iPhone 18, iPhone Air |
| iPad | iPad Pro (12,9 pouces) (4e génération), iPad Pro (11 pouces) | iPad Pro 13 pouces et iPad Air (puces M) |
| Google Pixel | Pixel 5 | Pixel 6 et suivants |
| Samsung | Gamme Galaxy S21 | Modèles Galaxy S plus récents |
| Mac | MacBook Air, MacBook Pro 13 et 16 | Les cadres Mac utilisent une image de fond avec un décalage plutôt qu’un cadre d’appareil |
En pratique, si vous capturez sur le simulateur le plus récent, il n’existe peut-être aucun cadre pour lui. Vos options : capturer sur un appareil qui a un cadre (en acceptant que la taille de son écran ne corresponde pas forcément à l’emplacement du store que vous visez), forcer un type d’appareil avec force_device_type, ou vous passer de cadres et utiliser une mise en page plein cadre.
Envoyer avec deliver et supply
# iOS: upload only screenshots, replacing what's there
fastlane deliver --skip_binary_upload --skip_metadata --overwrite_screenshots
# Android: upload only images and screenshots
fastlane supply --skip_upload_apk --skip_upload_aab \
--skip_upload_metadata --skip_upload_changelogsdeliver lit fastlane/screenshots, avec un sous-dossier par langue, et déduit le type d’appareil de la résolution de chaque image : chaque fichier doit donc avoir une taille acceptée avant l’envoi. supply lit fastlane/metadata/android/<locale>/images/, avec les dossiers phoneScreenshots, sevenInchScreenshots et tenInchScreenshots. Enchaînés dans une lane, la capture et l’envoi tiennent en une seule commande :
lane :screenshots do
snapshot
frameit(white: true)
deliver(skip_binary_upload: true, skip_metadata: true,
overwrite_screenshots: true)
endSi vous n’utilisez pas fastlane mais voulez quand même éviter l’envoi manuel, nous avons écrit sur l’envoi direct sur les stores depuis un outil de design.
Les accrocs à prévoir
Aucun de ces points n’est une raison de renoncer à fastlane, mais chacun vous coûtera du temps la première semaine si vous ne vous y attendez pas.
Les tests de captures sont lents, gardez-les à part
Une exécution, c’est à peu près chaque écran, multiplié par chaque appareil, multiplié par chaque langue. Trois appareils et dix langues, ce sont trente passages dans votre test. Gardez les tests de captures dans leur propre scheme ou test plan pour qu’ils ne tournent pas avec chaque test unitaire, et déclenchez-les sur les branches de release ou à la main plutôt qu’à chaque commit.
Attendez le contenu, pas une durée
Une cause fréquente de capture ratée, c’est de capturer un instant trop tôt : un indicateur de chargement, une image à moitié chargée, une liste encore en pleine animation. Dans les tests d’interface, attendez qu’un élément précis existe (waitForExistence(timeout:) sur iOS, une idling resource Espresso ou une attente UI Automator sur Android) avant d’appeler snapshot. Les pauses fixes marchent sur votre machine et échouent sur un runner de CI plus lent.
Rendez les données de démo déterministes
Si la capture affiche des dates, « il y a 3 jours » change tous les jours et les totaux dérivent quand les fixtures changent. Figez l’horloge dans votre mode données de démo, utilisez des fixtures fixes, et les captures ne changeront que quand l’interface changera. Ça rend aussi le résultat comparable en revue de code, ce qui est l’un des vrais avantages de garder ses captures sous contrôle de version.
Une interface traduite n’est que la moitié d’une capture localisée
snapshot vous donne gratuitement l’interface de l’app dans chaque langue. Les titres de title.strings restent à écrire pour chaque langue, et la traduction littérale d’un titre anglais percutant l’est rarement autant. Notre guide sur la localisation des captures d’écran App Store explique ce qu’il faut adapter au-delà des mots.
La CI a besoin d’un Mac avec les bons simulateurs
snapshot tourne sur macOS avec Xcode, donc la CI implique un runner macOS sur lequel sont installés les runtimes de simulateur que votre Snapfile mentionne. Les noms d’appareils du Snapfile doivent correspondre à des simulateurs présents sur ce runner : figez la version de Xcode utilisée par votre CI et mettez à jour le Snapfile quand vous passez à une nouvelle.
Quand l’automatisation est rentable, et quand elle ne l’est pas
Nous développons un outil de design, alors gardez ça en tête en nous lisant. Mais fastlane est vraiment la bonne réponse pour certaines équipes.
| fastlane (snapshot + frameit) | Un outil de design ou un générateur | |
|---|---|---|
| Coût | Gratuit, open source | De la formule gratuite aux formules payantes |
| Mise en place | Tests d’interface, Snapfile, Framefile, Ruby et ImageMagick | Importer les captures, choisir une mise en page |
| Relancer après un changement d’interface | Une commande, tous les appareils et toutes les langues | Recapturer et remplacer à la main |
| Contrôle visuel | Configuration : police, couleurs, marges, fond | Un canevas visuel |
| Cadres d’appareil | Ce que contient le dépôt de cadres | Selon la bibliothèque de l’outil |
| Sous contrôle de version | Oui | Généralement non |
L’automatisation est généralement rentable quand :
- Vous publiez toutes les quelques semaines et l’interface visible sur vos captures change d’une version à l’autre.
- Vous publiez dans de nombreuses langues, où chaque capture se multiplie par le nombre de langues.
- Vous avez déjà des tests d’interface, ou vous en voulez de toute façon.
- Quelqu’un dans l’équipe est à l’aise pour gérer une chaîne d’outils Ruby et ImageMagick dans la CI.
Elle l’est rarement quand :
- Vous publiez en une ou deux langues et mettez à jour vos captures quelques fois par an.
- Vos captures relèvent du design : mises en page sur mesure, illustrations, série panoramique.
- Vos écrans demandent un état difficile à atteindre depuis un test d’interface (paiements, données en direct, autres utilisateurs).
Beaucoup d’équipes coupent la poire en deux : snapshot pour des captures propres et localisées, et un outil de design pour la couche marketing par-dessus. Notre comparatif Launch Shots vs fastlane frameit détaille cette approche, et si vous hésitez sur un outil de design, notre guide pour créer des captures d’écran App Store dans Figma présente l’alternative manuelle. Launch Shots se range dans le second camp : vous apportez vos captures (y compris celles de snapshot), et il s’occupe de la mise en page, de la traduction et de l’envoi.
Des captures d’écran prêtes pour les stores en quelques minutes — gratuit, sans filigrane à l’export.
Launch Shots est gratuit pour commencer. Tous les modèles (plus de 110), plus de 220 cadres d’appareil et des mockups 3D, la traduction IA et l’envoi direct vers App Store Connect et la Google Play Console. Sans carte bancaire.
Commencer gratuitement →En bref
- iOS : cible UI Test,
fastlane snapshot init,setupSnapshot(app),snapshot("01Home"), un Snapfile avec appareils, langues etoverride_status_bar(true). - Android :
tools.fastlane:screengrab,LocaleTestRule,CleanStatusBar,Screengrab.screenshot(), un Screengrabfile. - frameit : ImageMagick, un
Framefile.jsonavec un fond, untitle.stringspar langue qui commence par une ligne vide. - Vérifiez que le dépôt de cadres contient votre appareil de capture avant d’en dépendre.
- deliver et supply se chargent de l’envoi ; vérifiez d’abord que chaque fichier a une taille acceptée. Notre référence des tailles de captures et la checklist ASO de lancement vous aident pour le reste de la fiche.
Questions fréquentes
05- Qu’est-ce que fastlane snapshot ?
- fastlane snapshot est un outil open source qui automatise les captures d’écran iOS. Il exécute vos tests d’interface Xcode sur les simulateurs et dans les langues listés dans un Snapfile, et enregistre une capture à chaque endroit où un test appelle snapshot("name"). Les résultats sont rangés dans un dossier par langue que fastlane deliver peut envoyer sur App Store Connect. C’est gratuit et ça fait partie de la boîte à outils fastlane.
- fastlane frameit prend-il en charge les derniers iPhone ?
- Les cadres d’appareil de frameit proviennent du dépôt séparé frameit-frames et sont ajoutés après la sortie des nouveaux appareils. Quand nous avons vérifié en octobre 2026, le dépôt contenait des cadres pour la gamme iPhone 17, mais aucun pour les modèles iPhone 18 ni pour l’iPhone Air, et son cadre d’iPad Pro le plus récent était le 12,9 pouces de 4e génération. Vérifiez dans le dépôt l’appareil sur lequel vous capturez avant de compter dessus.
- fastlane snapshot vaut-il encore la peine ?
- Oui, si vous publiez souvent, dans plusieurs langues, et que l’interface de votre app change d’une version à l’autre, car régénérer toutes les captures ne demande plus qu’une commande. Pour une app en une seule langue avec des mises à jour occasionnelles, le temps passé à écrire et maintenir des tests d’interface pour les captures dépasse souvent celui qu’il faut pour capturer une poignée d’écrans à la main.
- Comment obtenir une barre d’état propre avec fastlane snapshot ?
- Ajoutez override_status_bar(true) dans votre Snapfile. fastlane snapshot règle alors la barre d’état de chaque simulateur sur 9:41, batterie pleine et réseau au maximum, avant de capturer. Pour un contrôle plus fin, override_status_bar_arguments transmet vos propres options simctl status_bar. Sur Android, l’utilitaire CleanStatusBar de screengrab fait la même chose grâce au mode démo de l’interface système, à partir de l’API 23.
- frameit peut-il ajouter des titres marketing aux captures ?
- Oui. frameit lit un fichier Framefile.json pour la mise en page, les polices et les couleurs, et des fichiers title.strings et keyword.strings par langue pour le texte, indexés par une partie du nom de fichier de la capture. Une image de fond est obligatoire pour les titres. Il produit des captures encadrées avec un titre au-dessus ou en dessous de l’appareil, mais la mise en page se règle par configuration, pas sur un canevas visuel.
