Screenshot Test è un controllo automatizzato dell’interfaccia utente catturando e confrontando screenshot degli schermi dell’app con immagini di riferimento. A differenza dei golden test, gli screenshot test vengono eseguiti su dispositivi reali o emulatori, catturano schermi completi con navigazione, elementi di sistema e animazioni, e utilizzano UI Automator (Android) o XCUITest (iOS) per interagire con l’app. Maggiori dettagli in documentazione Android UI Automator.
Punti chiave
Screenshot Test è un test end-to-end dell’interfaccia utente in cui il test apre una schermata dell’app, esegue azioni (tap, inserimento testo, scroll) e scatta uno screenshot dello stato risultante. Lo screenshot viene confrontato con una baseline memorizzata nel repository. Se gli screenshot differiscono — il test fallisce. Gli screenshot test rilevano regressioni visive che i test unitari non possono vedere: margini errati, elementi sovrapposti, colori sbagliati.
Perché servono screenshot test se abbiamo già i golden test? — i golden test verificano i componenti isolatamente: un pulsante, una carta, un testo. Gli screenshot test verificano un’intera schermata in un ambiente il più possibile vicino alla produzione: navigazione reale, dati reali (o mock il più realistici possibile), font di sistema reali, barra di stato reale. Solo uno screenshot test mostrerà che un pulsante si sovrappone a un altro elemento su un dispositivo reale.
Valore commerciale — secondo Google (2023), i bug visivi costituiscono il 15-25% di tutti i bug delle app mobili. Gli screenshot test automatizzano il controllo della qualità visiva che prima veniva eseguito manualmente dagli ingegneri QA. Uno screenshot test sostituisce 5-10 minuti di test manuale di una schermata. Per un’app con 50 schermate, il risparmio è di 4-8 ore-uomo per esecuzione di regressione. Gli screenshot test si ripagano in 2-3 cicli di rilascio.
I golden test sono più veloci e semplici: il rendering di un componente in un buffer off-screen richiede millisecondi, non necessita di un dispositivo ed è stabile su CI. Gli screenshot test sono più realistici: catturano uno schermo reale con elementi di sistema, supportano animazioni e navigazione e funzionano su dispositivi reali. La scelta dipende dall’obiettivo: feedback rapido per lo sviluppatore (golden) o massimo realismo prima del rilascio (screenshot).
| Caratteristica | Screenshot Test | Golden Test |
|---|---|---|
| Velocità | 2-30 secondi | 50-200 ms |
| Realismo | Massimo (dispositivo reale) | Limitato (off-screen) |
| Richiede dispositivo | Sì (emulatore/fisico) | No (JVM, XCTest) |
| Animazioni | Supporta | Non supporta |
| Navigazione | Scenari multi-step | Componente singolo |
| Instabilità | Alta (rete, temporizzazione) | Media (GPU, font) |
| Parallelismo | Device Farm (Firebase, AWS) | JVM/XCTest multithread |
Golden + Screenshot — usa i golden test per ogni componente UI nella libreria di componenti (Design System). L’80% delle regressioni visive vengono catturate a livello di componente. Screenshot test — per i percorsi utente critici: onboarding, login, flusso di pagamento, carrello. Il 20% delle regressioni relative all’integrazione dei componenti su uno schermo reale vengono catturate solo dagli screenshot test. In IT Sectr usiamo un rapporto 80/20: 400 golden + 100 screenshot.
Quando uno screenshot test non è necessario — se la schermata consiste in contenuto statico senza interattività, un golden test del componente fornisce lo stesso livello di verifica a un costo inferiore. Se la schermata cambia dinamicamente (feed, chat), uno screenshot test richiede una configurazione complessa dei dati e tempi di attesa. In questi casi, usa screenshot per lo stato base (lista vuota, caricamento) e golden per le singole carte nella lista.
UI Automator è un framework Android per il test UI tra applicazioni. Permette di scattare screenshot tramite UiDevice.takeScreenshot(). A differenza di Espresso (funziona all’interno di una singola app), UI Automator può interagire con i dialoghi di sistema (permessi, notifiche) e altre app. Uno screenshot test su UI Automator: aprire l’app, attendere il caricamento, scattare uno screenshot, confrontare con la baseline.
class LoginScreenScreenshotTest {
@get:Rule
val rule = ComposeTestRule.createAndroidComposeRule<MainActivity>()
@Test
fun login_screen_default() {
val device = UiDevice.getInstance(
InstrumentationRegistry.getInstrumentation()
)
// Attendiamo il caricamento della schermata
IdlingRegistry.getInstance().waitForIdle()
// Facciamo uno screenshot
val screenshot = device.takeScreenshot()
val golden = loadGolden("login_default.png")
// Confrontiamo con il riferimento
val diff = ImageComparator.compare(screenshot, golden)
assertTrue(diff.similarity > 0.98)
}
}
Firebase Test Lab è un servizio Google Cloud per eseguire test instrumentati su centinaia di dispositivi reali in parallelo. Gli screenshot test su Firebase Test Lab catturano schermate su diversi dispositivi (Pixel 7, Galaxy S24, Xiaomi 14) e le confrontano con le baseline. Vantaggio: un test verifica l’UI su 20 dispositivi in 10-15 minuti. Svantaggio: costo ($1-5 per test su 20 dispositivi). Firebase Test Lab si integra con CI tramite gcloud CLI o plugin Gradle.
Shot è una libreria per screenshot testing su Android che semplifica la creazione e il confronto di screenshot. Shot funziona sopra Espresso e UI Automator, aggiungendo gestione golden (creare, aggiornare, eliminare), confronto con soglia (pixel o percentuali) e generazione di report HTML. Shot è adatto a progetti che vogliono implementare rapidamente screenshot testing senza scrivere la propria infrastruttura di confronto immagini.
XCUITest è il framework di Apple per il test UI di app iOS, iPadOS e tvOS. Gli screenshot test su XCUITest usano XCUIScreen.main.screenshot() per catturare lo schermo e XCAttachment per salvare gli screenshot. XCUITest simula le azioni dell’utente: tap, swipe, typeText, e scatta screenshot dopo ogni passaggio. In Xcode 16+ è stato aggiunto il supporto integrato per il confronto degli screenshot con le baseline tramite XCTAttachment.
final class LoginScreenScreenshotTests: XCTestCase {
var app: XCUIApplication!
override func setUp() {
super.setUp()
app = XCUIApplication()
app.launch()
}
func test_login_initial_state() {
let loginButton = app.buttons["login_button"]
XCTAssertTrue(loginButton.exists)
// Facciamo uno screenshot
let screenshot = app.screenshot()
let attachment = XCTAttachment(screenshot: screenshot)
attachment.name = "Login-Screen-Initial"
attachment.lifetime = .keepAlways
add(attachment)
// Confronto con il riferimento (richiede XCTAttachment + golden)
assertScreenshot(
screenshot: screenshot,
goldenName: "login_initial_state"
)
}
}
Xcode Cloud è il CI cloud di Apple per compilare e testare app iOS. Xcode Cloud supporta l’esecuzione di test XCUITest su simulatori. Gli screenshot test possono essere eseguiti su più simulatori in parallelo (iPhone 15, iPhone 15 Pro Max, iPad Pro). Risultati: XCResult Bundle con allegati. Xcode Cloud non è integrato in GitHub/GitLab — usa Xcode Cloud Webhooks per l’integrazione. Alternativa: GitHub Actions con macos-14 e xcodebuild.
Framework di confronto — iOSSnapshotTestCase (Uber) funziona anche per screenshot test se eseguito su un simulatore. SwiftSnapshotTesting (pointfree) è più orientato ai golden test di componenti. Per screenshot test su iOS, usa gli strumenti integrati di XCUITest + XCTAttachment + un ImageComparator personalizzato (Pixelmator o AImage). Su CI usa il simulatore — su dispositivi reali gli screenshot test funzionano solo tramite Device Farm (AWS Device Farm).
Gestione delle baseline — gli screenshot di riferimento sono memorizzati nel repository (Git LFS) o in S3. Ogni screenshot viene nominato secondo il template: {testName}_{device}_{orientation}_{locale}.png. Esempio: loginScreenPixel7PortraitRu.png. Quando si aggiunge un nuovo dispositivo o locale, viene creata una nuova baseline. Quando si modifica l’UI, le vecchie baseline vengono sostituite con nuove dopo la revisione del codice. La baseline fa parte della base di codice, come i sorgenti dei test.
Pipeline CI — (1) Compilare l’app. (2) Eseguire screenshot test su emulatori/simulatori. (3) Confrontare gli screenshot con le baseline. (4) In caso di discrepanza — generare immagine diff. (5) Caricare artefatti diff (actual, expected, diff — tre file). (6) Pubblicare report HTML con tabella dei risultati. (7) Se la soglia viene superata — il test fallisce. (8) Il revisore esamina gli artefatti diff e prende una decisione: approvare (aggiornare baseline) o rifiutare (correggere il codice).
Soglia e tolleranza — il confronto assoluto pixel per pixel è troppo severo. Usa SSIM (Indice di Similarità Strutturale) o MSE (Errore Quadratico Medio). SSIM 0.98 = 98% di similarità strutturale — una buona soglia. Schermate diverse possono richiedere soglie diverse: tema scuro (più nero — maggiore precisione), gradienti (più rumore — minore precisione). Configura la soglia per test tramite il parametro: @ScreenshotTest(threshold = 0.99).
Device Farm vs Simulatore — i test su dispositivi reali (Firebase Test Lab, AWS Device Farm) offrono il massimo realismo ma sono lenti e a pagamento. I test su simulatori/emulatori sono veloci e gratuiti ma non mostrano le caratteristiche dei dispositivi reali (GPU diverse, riproduzione colore del display, densità di pixel). Strategia: simulatore per la verifica pre-merge (5 minuti), Device Farm per i test notturni (30 minuti, 20 dispositivi). In IT Sectr usiamo Firebase Test Lab per esecuzioni notturne sui top 10 dispositivi Android.
Domande frequenti
Golden Test — per la verifica rapida di singoli componenti UI a ogni commit (50-200 ms). Screenshot Test — per la verifica E2E di intere schermate su dispositivi reali prima del rilascio (2-30 secondi). Usa entrambi: golden per i componenti del Design System, screenshot per i percorsi utente critici. Un rapporto 80/20 è ottimale per la maggior parte dei progetti.
SSIM 0.98 è una buona soglia iniziale per la maggior parte delle schermate. Per il tema scuro, puoi usare 0.99 (contrasto più alto — confronto più preciso). Per schermate con gradienti e immagini — 0.95-0.97. Non usare il confronto assoluto pixel per pixel (MSE = 0) — produce il 20-30% di falsi positivi a causa di anti-aliasing e differenze GPU. Configura la soglia individualmente per ogni test.
A ogni modifica intenzionale dell’UI — modifica di colori, font, margini, icone, aggiunta/rimozione di elementi. Non aggiornare le baseline quando cambia l’ambiente (versione OS, font su CI) — questo è un segno di test instabile. Le baseline vengono aggiornate solo localmente dallo sviluppatore dopo la revisione del codice: eliminare le vecchie baseline, eseguire i test con record=true, verificare i nuovi screenshot, committare.
Sì — tramite Espresso su Android e XCUITest su iOS. Espresso funziona all’interno del processo dell’app e non richiede Accessibility Service (come UI Automator). XCUITest è il framework standard di Apple per i test UI. Per gli screenshot test la differenza è minima: XCUITest è leggermente più stabile (API nativa Apple), UI Automator è leggermente più flessibile (interazione tra processi).
Se configurati correttamente — no. Pre-merge: esegui solo screenshot test sulle schermate modificate (30-60 secondi). Notturni: esecuzione completa su Device Farm (30 minuti, 20 dispositivi). Tempo di esecuzione degli screenshot test su emulatore: 2-10 secondi per schermata. 20 schermate = 40-200 secondi. Questo è meno del tempo di test manuale di una singola schermata (5-10 minuti).
Riepilogo
Svilupperemo un'applicazione mobile chiavi in mano
IT Sectr crea applicazioni iOS e Android per startup e aziende dal 2017. Ti consulteremo e ti proporremo la soluzione migliore.
Leggi anche