Automatizzare gli screenshot per gli store con fastlane snapshot e frameit
8 min di lettura

Automatizzare gli screenshot per gli store con fastlane snapshot e frameit

Configura fastlane snapshot, screengrab e frameit per acquisire, incorniciare e caricare gli screenshot dalla CI, e capisci quando l'automazione conviene.

A
Scritto da
Inizia a leggere

fastlane automatizza gli screenshot per gli store in tre fasi. snapshot (iOS) e screengrab (Android) eseguono i tuoi test UI su simulatori o emulatori in ogni lingua che elenchi e salvano uno screenshot in ogni punto che segni. frameit ci mette intorno cornici dei dispositivi, uno sfondo e un titolo. deliver e supply caricano i risultati su App Store Connect e Google Play. Una volta configurato, rigenerare tutti gli screenshot è un solo comando.

Quell'ultima frase è tutto il fascino, e la configurazione è tutto il costo. Questa guida passa in rassegna ogni pezzo con una configurazione funzionante, poi prova a dire onestamente quando ne vale la pena.

In sintesi
  • fastlane snapshot esegue i test UI di Xcode sui dispositivi e nelle lingue di uno Snapfile e acquisisce uno screenshot ogni volta che un test chiama snapshot("name").
  • screengrab è l'equivalente per Android: esegue i test di strumentazione, e Screengrab.screenshot("name") salva ogni schermata in fastlane/metadata/android.
  • frameit aggiunge cornici dei dispositivi, uno sfondo e titoli a partire da un Framefile.json e da file title.strings per ogni lingua; richiede ImageMagick.
  • Le cornici di frameit arrivano in ritardo rispetto ai nuovi dispositivi: a ottobre 2026 il suo repository si fermava alla famiglia iPhone 17, all'iPad Pro da 12,9 pollici (quarta generazione) e al Pixel 5.
  • L'automazione conviene per le app che pubblicano spesso in più lingue; con una sola lingua e release rare, acquisire a mano di solito è più veloce.

Come funziona fastlane snapshot

fastlane snapshot si appoggia ai test UI di Xcode. Scrivi un test UI che attraversa la tua app; in ogni schermata che vale la pena mostrare, chiama snapshot("01Home"). snapshot esegue il test una volta per ogni combinazione di dispositivo e lingua e raccoglie le immagini in fastlane/screenshots/<language>/.

Configurazione

  1. Aggiungi un target UI Test al progetto Xcode, se non ce l'hai già.
  2. Esegui fastlane snapshot init nella cartella del progetto. Crea uno Snapfile e un file SnapshotHelper.swift.
  3. Aggiungi SnapshotHelper.swift al target UI Test.

Il test UI

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) passa all'app la lingua e la locale correnti: è così che un solo test produce ogni set localizzato. L'argomento -demoData è una nostra convenzione: l'app lo controlla nelle build di debug e carica contenuti di esempio, così nessuno screenshot mostra uno stato vuoto. Mettere un numero davanti ai nomi tiene i file nell'ordine di caricamento.

Lo 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"])

I nomi dei dispositivi devono corrispondere ai simulatori installati nel tuo Xcode; xcrun simctl list devicetypes li mostra. Un simulatore iPhone 17 Pro Max acquisisce a 1320 × 2868, una delle dimensioni che App Store Connect accetta per lo slot iPhone più grande. Poi esegui:

fastlane snapshot

Altre opzioni di snapshot da conoscere: localize_simulator imposta anche la lingua di sistema del simulatore, erase_simulator fa partire ogni esecuzione da un dispositivo pulito, reinstall_app disinstalla prima l'app, e override_status_bar_arguments accetta i tuoi flag di simctl status_bar. Se vuoi sapere cosa fanno quei flag, la nostra guida agli screenshot puliti da simulatore ed emulatore li spiega, insieme ai comandi manuali che snapshot automatizza.

screengrab: l'equivalente per Android

screengrab fa lo stesso lavoro con i test di strumentazione di Android. Aggiungi la libreria alle dipendenze dei test:

// app/build.gradle
androidTestImplementation 'tools.fastlane:screengrab:x.x.x'

Assicurati che src/debug/AndroidManifest.xml includa i permessi elencati nella documentazione (come DISABLE_KEYGUARD), poi scrivi il 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 cambia la locale a ogni esecuzione, e CleanStatusBar è un wrapper attorno alla modalità demo della System UI di Android; la documentazione precisa che richiede il livello API 23 o superiore. Compila gli APK, genera uno Screengrabfile ed eseguilo:

./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)

Per impostazione predefinita gli screenshot finiscono in fastlane/metadata/android/<locale>/images/phoneScreenshots, che è esattamente dove supply li va a cercare. Una cosa da controllare su Android: Google Play rifiuta gli screenshot in cui il lato lungo supera il doppio del lato corto, quindi scegli un profilo di emulatore che non sia più alto di 2:1.

frameit: cornici dei dispositivi e titoli

frameit prende le acquisizioni grezze e le inserisce nelle cornici dei dispositivi. Richiede ImageMagick (brew install imagemagick). Le cornici si scaricano automaticamente la prima volta che lo esegui.

fastlane frameit            # iOS and Mac screenshots
fastlane frameit android    # Android screenshots
fastlane frameit silver     # silver frame variants

Una cornice del dispositivo da sola non rende lo screenshot automaticamente pronto per l'App Store: l'immagine incorniciata potrebbe non corrispondere a nessuna dimensione accettata da App Store Connect. La documentazione di fastlane dice che per i caricamenti sull'App Store ti serve un Framefile.json con titoli e sfondo, che produce invece un'immagine promozionale completa.

Framefile.json

Mettilo nella cartella 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" }
  ]
}

Ogni voce di data si applica agli screenshot il cui nome file contiene il suo filter, e può sovrascrivere i valori predefiniti. Il testo vero e proprio sta in file per ogni lingua, title.strings e, se vuoi, keyword.strings, dentro ogni cartella della lingua:


"01Home" = "See every euro, every month";
"02Budget" = "Budgets that adjust themselves";
"03AddExpense" = "Log a purchase in two taps";

Quella riga vuota iniziale è voluta: la documentazione dice che il file deve cominciare con una riga vuota e deve essere in UTF-8 o in UTF-16 BE con BOM. Dice anche che, se vuoi i titoli, devi fornire uno sfondo. Se i titoli non compaiono, controlla prima queste tre cose.

Le cornici di frameit arrivano in ritardo sui nuovi dispositivi

Le cornici di frameit arrivano dal repository separato frameit-frames, e vengono aggiunte dopo l'uscita dei dispositivi. Quando abbiamo controllato a ottobre 2026:

FamigliaCornice più recente nel repositoryNon ancora presente
iPhoneiPhone 17, 17 Pro, 17 Pro MaxModelli iPhone 18, iPhone Air
iPadiPad Pro (12,9 pollici) (quarta generazione), iPad Pro (11 pollici)iPad Pro da 13 pollici e iPad Air (serie M)
Google PixelPixel 5Pixel 6 e successivi
SamsungFamiglia Galaxy S21Modelli Galaxy S più recenti
MacMacBook Air, MacBook Pro 13 e 16Le cornici Mac usano un'immagine di sfondo più un offset anziché una cornice del dispositivo

In pratica, se acquisisci sul simulatore più recente, potrebbe non esserci una cornice per quel dispositivo. Le opzioni sono acquisire su un dispositivo che ha una cornice (accettando che le dimensioni dello schermo potrebbero non corrispondere allo slot dello store che vuoi), forzare un tipo di dispositivo con force_device_type, oppure rinunciare alle cornici e usare un layout a tutta pagina.

Caricare con deliver e 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_changelogs

deliver legge fastlane/screenshots con una sottocartella per lingua e ricava il tipo di dispositivo dalla risoluzione di ogni immagine, quindi prima del caricamento ogni file deve avere una dimensione accettata. supply legge fastlane/metadata/android/<locale>/images/, con le cartelle phoneScreenshots, sevenInchScreenshots e tenInchScreenshots. Concatenati in una lane, dall'acquisizione al caricamento basta un comando:

lane :screenshots do
  snapshot
  frameit(white: true)
  deliver(skip_binary_upload: true, skip_metadata: true,
          overwrite_screenshots: true)
end

Se non usi fastlane ma vuoi comunque evitare il caricamento manuale, abbiamo scritto di come caricare direttamente sugli store da uno strumento di design.

Intoppi pratici da mettere in conto

Nessuno di questi è un motivo per non usare fastlane, ma ognuno ti costa tempo nella prima settimana se non te lo aspetti.

I test per gli screenshot sono lenti, quindi tienili separati

Un'esecuzione vale più o meno ogni schermata, per ogni dispositivo, per ogni lingua. Tre dispositivi e dieci lingue sono trenta passaggi nel tuo test. Tieni i test per gli screenshot in uno scheme o in un test plan dedicato, così non partono con ogni test unitario, e avviali sui branch di release o a mano invece che a ogni commit.

Aspetta il contenuto, non il tempo

Una causa frequente di uno screenshot venuto male è acquisire un attimo troppo presto: uno spinner, un'immagine caricata a metà, una lista ancora in animazione. Nei test UI, aspetta che un elemento specifico esista (waitForExistence(timeout:) su iOS, una idling resource di Espresso o un'attesa di UI Automator su Android) prima di chiamare snapshot. Le pause fisse funzionano sulla tua macchina e falliscono su un runner di CI più lento.

Rendi deterministici i dati demo

Se lo screenshot mostra delle date, «3 giorni fa» cambia ogni giorno e i totali si spostano quando cambiano le fixture. Blocca l'orologio nella modalità dati demo, usa fixture fisse, e gli screenshot cambieranno solo quando cambia l'interfaccia. In più l'output diventa confrontabile in fase di review, che è uno dei veri vantaggi di tenere gli screenshot nel controllo di versione.

L'interfaccia tradotta è solo metà di uno screenshot localizzato

snapshot ti dà gratis l'interfaccia dell'app in ogni lingua. I titoli in title.strings vanno comunque scritti lingua per lingua, e la traduzione letterale di un titolo inglese d'effetto spesso non ha lo stesso effetto. La nostra guida su come localizzare gli screenshot dell'App Store spiega cosa adattare oltre alle parole.

La CI ha bisogno di un Mac con i simulatori giusti

snapshot gira su macOS con Xcode, quindi per la CI serve un runner macOS con installati i runtime dei simulatori indicati nello Snapfile. I nomi dei dispositivi nello Snapfile devono corrispondere a simulatori presenti su quel runner, quindi fissa la versione di Xcode usata dalla CI e aggiorna lo Snapfile quando passi a una nuova.

Quando l'automazione conviene, e quando no

Noi sviluppiamo uno strumento di design, quindi prendi la nostra opinione tenendone conto. Ma per alcuni team fastlane è davvero la risposta giusta.

fastlane (snapshot + frameit)Uno strumento di design o un generatore
CostoGratuito, open sourceDa piani gratuiti a piani a pagamento
ConfigurazioneTest UI, Snapfile, Framefile, Ruby e ImageMagickCarichi le acquisizioni, scegli un layout
Rigenerare dopo una modifica all'interfacciaUn comando, tutti i dispositivi e le lingueRiacquisisci e sostituisci a mano
Controllo visivoConfigurazione: font, colori, padding, sfondoUn canvas visivo
Cornici dei dispositiviQuelle presenti nel repository delle corniciDipende dalla libreria dello strumento
Nel controllo di versioneSìDi solito no

L'automazione di solito conviene quando:

  • Pubblichi una release ogni poche settimane e l'interfaccia che compare negli screenshot cambia tra una release e l'altra.
  • Pubblichi in molte lingue, dove ogni acquisizione si moltiplica per il numero di locale.
  • Hai già dei test UI, o li vuoi comunque.
  • Qualcuno nel team è a suo agio nel gestire una toolchain Ruby e ImageMagick nella CI.

Di solito non conviene quando:

  • Pubblichi in una o due lingue e aggiorni gli screenshot poche volte l'anno.
  • Gli screenshot sono un problema di design: layout personalizzati, illustrazioni, un set panoramico.
  • Le tue schermate hanno bisogno di uno stato difficile da raggiungere da un test UI (pagamenti, dati in tempo reale, altri utenti).

Molti team scelgono una via di mezzo: snapshot per acquisizioni pulite e localizzate, e uno strumento di design per lo strato promozionale sopra. Il nostro confronto tra Launch Shots e fastlane frameit lo spiega nel dettaglio, e se stai valutando uno strumento di design, la nostra guida su come creare gli screenshot dell'App Store in Figma mostra l'alternativa manuale. Launch Shots sta nel secondo gruppo: porti le tue acquisizioni (anche quelle di snapshot), e lui si occupa di layout, traduzione e caricamento.

Provalo ora

Crea screenshot pronti per lo store in pochi minuti: gratis, senza filigrana sugli export.

Launch Shots è gratis per iniziare. Tutti i template (oltre 110), più di 220 cornici dei dispositivi e mockup 3D, localizzazione AI e caricamento diretto su App Store Connect e Google Play Console. Nessuna carta di credito richiesta.

Inizia gratis →

In breve

  • iOS: target UI Test, fastlane snapshot init, setupSnapshot(app), snapshot("01Home"), uno Snapfile con dispositivi, lingue e override_status_bar(true).
  • Android: tools.fastlane:screengrab, LocaleTestRule, CleanStatusBar, Screengrab.screenshot(), uno Screengrabfile.
  • frameit: ImageMagick, Framefile.json con uno sfondo, title.strings per ogni lingua che cominci con una riga vuota.
  • Prima di farci affidamento, controlla che il repository delle cornici abbia il dispositivo su cui acquisisci.
  • deliver e supply caricano; prima controlla che ogni file abbia una dimensione accettata. Il nostro riferimento sulle dimensioni degli screenshot e la checklist ASO per il lancio ti aiutano con il resto della scheda.

Domande frequenti

05
Cos'è fastlane snapshot?
fastlane snapshot è uno strumento open source che automatizza gli screenshot iOS. Esegue i tuoi test UI di Xcode sui simulatori e nelle lingue che elenchi in uno Snapfile, e salva uno screenshot ogni volta che un test chiama snapshot("name"). I risultati finiscono in cartelle separate per lingua che fastlane deliver può caricare su App Store Connect. È gratuito e fa parte della toolchain di fastlane.
fastlane frameit supporta gli iPhone più recenti?
Le cornici dei dispositivi di frameit arrivano dal repository separato frameit-frames e vengono aggiunte dopo l'uscita dei nuovi dispositivi. Quando abbiamo controllato a ottobre 2026, il repository aveva le cornici della famiglia iPhone 17 ma nessuna per i modelli iPhone 18 o per iPhone Air, e la cornice di iPad Pro più recente era quella da 12,9 pollici di quarta generazione. Prima di farci affidamento, controlla nel repository il dispositivo su cui acquisisci.
Vale ancora la pena usare fastlane snapshot?
Ne vale la pena quando pubblichi spesso, in più lingue, e l'interfaccia dell'app cambia tra una release e l'altra, perché rigenerare tutti gli screenshot diventa un solo comando. Per un'app in una sola lingua e con release occasionali, il tempo per scrivere e mantenere i test UI per gli screenshot spesso supera quello per acquisire a mano una manciata di schermate.
Come ottengo una barra di stato pulita con fastlane snapshot?
Imposta override_status_bar(true) nello Snapfile. fastlane snapshot porterà la barra di stato di ogni simulatore alle 9:41, con batteria carica e segnale pieno, prima di acquisire. Per un controllo più fine, override_status_bar_arguments passa i tuoi flag di simctl status_bar. Su Android, l'helper CleanStatusBar di screengrab fa lo stesso usando la modalità demo della System UI da API 23 in poi.
frameit può aggiungere titoli promozionali agli screenshot?
Sì. frameit legge un Framefile.json per layout, font e colori, e file title.strings e keyword.strings per ogni lingua per i testi, associati a una parte del nome del file dello screenshot. Per i titoli serve un'immagine di sfondo. Produce screenshot incorniciati con un titolo sopra o sotto il dispositivo, anche se le opzioni di layout sono configurazione e non un canvas di design visivo.