Golden Test — ce este, cum funcționează snapshot-testarea și aplicarea

Autor: IT Sectr Publicat: 2026-04-10 Timp de citire: 9 min

Golden Test (snapshot-test, testare etalon) — metodă de testare vizuală a UI în care randarea curentă a componentei este comparată cu o imagine etalon salvată anterior (fișier golden). Dacă modificările pixelilor depășesc un prag stabilit, testul eșuează și generează o imagine diff. Dezvoltatorul verifică diff-ul și fie acceptă modificările (actualizează golden), fie remediază bug-ul. Mai multe în articolul Meta Engineering despre Paparazzi.

Principalele puncte

  • Golden Test — compararea UI-ului curent cu imaginea etalon pentru detectarea regresiilor vizuale
  • Imaginea diff — la nepotrivire, golden-test generează un diff cu evidențierea pixelilor modificați
  • Android — Paparazzi și Roborazzi pentru screenshot-testarea componentelor compose și view
  • iOS — SwiftSnapshotTesting (pointfree.co) și iOSSnapshotTestCase de la Uber pentru SwiftUI și UIKit
  • Integrarea CI — golden-testurile rulează pe CI și eșuează la modificări neașteptate ale UI

Ce este Golden Test și cum funcționează?

Golden Test — este o verificare automatizată a aspectului componentei prin compararea pixel cu pixel cu etalonul. Proces: (1) dezvoltatorul sau testerul realizează prima captură a componentei — acesta este „golden“ (etalonul). (2) Fișierul golden este salvat în depozit lângă test. (3) La rulările ulterioare, testul randază din nou componenta și o compară cu golden-ul salvat. (4) Dacă imaginile coincid — testul este verde. Dacă diferă — testul este roșu cu diff. Decizia: fie modificările sunt așteptate (actualizăm golden), fie este o eroare.

Cum se generează golden — biblioteca randază componenta într-un buffer în afara ecranului (Android: Canvas, iOS: UIGraphicsImageRenderer) fără afișaj real. Aceasta înseamnă că golden-testurile funcționează pe CI fără emulator de ecran (virtual display), ceea ce accelerează execuția. Paparazzi pe Android folosește Layoutlib din Android Studio — același motor ca Layout Editor. iOSSnapshotTestCase folosește randarea UIKit în CGImage. Rezultatul — un fișier PNG de dimensiune fixă.

Dimensiunea fișierelor golden și gestionarea stocării

Fișierele golden — captura PNG a unui ecran (1080x1920) ocupă 200-800 KB în funcție de complexitate. Pentru un proiect cu 500 golden-testuri, aceasta înseamnă ~100-400 MB în depozit. Soluții: (1) stocarea golden în Git LFS. (2) Utilizarea compresiei PNG (pngcrush, oxipng). (3) Stocarea golden într-un stoc separat (S3) și descărcarea la construire. În IT Sectr stocăm golden în Git LFS cu un prag de 1 MB per fișier — acest lucru este suficient pentru 90% din teste.

Testele flaky golden și soluția lor

Testele flaky golden — principala problemă a golden-testurilor. GPU-uri diferite, versiuni de fonturi și anti-aliasing generează micro-diferențe în pixeli. Soluții: threshold (procentul admisibil de pixeli diferiți), fuzzy comparison (comparare neclară) și rularea pe aceiași agenți CI (același GPU, OS, versiune de emulator). În Paparazzi se utilizează compararea pixel-perfect, prin urmare agenții CI trebuie să fie identici.

Golden Test vs Screenshot Test: care este diferența?

Golden Test — este un tip de screenshot-testare cu un etalon fix. Termenul „golden“ înseamnă că etalonul a fost aprobat (acceptat) de echipă și stocat în depozit. Orice modificare a imaginii necesită o decizie conștientă a dezvoltatorului: actualizarea golden sau corectarea codului. Golden Test funcționează la nivelul componentelor individuale (Composable, UIView) și nu necesită un dispozitiv real.

Screenshot Test — un concept mai larg. Screenshot-testul poate captura întregul ecran cu date reale, navigație, bara de stare a sistemului și animații. Screenshot-testurile sunt adesea rulate pe dispozitive reale sau emulatoare prin UI Automator (Android) sau XCUITest (iOS). Golden-testurile funcționează în mediul unit-test (JVM, XCTest) fără emulator și capturează doar o singură componentă.

CaracteristicăGolden TestScreenshot Test
NivelComponentă/Composable/ViewEcran întreg
MediuUnit-test (buffer în afara ecranului)Dispozitiv/Emulator
Viteză50-200 ms per test2-30 secunde per test
AnimațiiNu sunt suportateSunt suportate (cu pauze)
CI fără GPUFuncționează (Layoutlib)Necesită emulator
Complexitatea configurăriiScăzutăRidicată (Emulator/Device Farm)
FlakinessMedie (GPU diferite)Ridicată (emulator, timp)

Strategia de acoperire: golden vs screenshot

Golden vs Screenshot — golden-testurile pentru verificarea componentelor UI individuale (buton, card, dialog) la fiecare commit. Screenshot-testurile — pentru verificarea E2E a ecranelor întregi înainte de lansare. Golden-testurile oferă feedback rapid dezvoltatorului, screenshot-testurile — încredere în integritatea întregii aplicații. În IT Sectr folosim golden-testuri pentru Pull Request (3-5 minute), iar screenshot-testuri — nightly (30-60 minute).

Paparazzi și Roborazzi: snapshot-testare pe Android

Paparazzi — bibliotecă de la Cash App (Square) care randază componente Android View și Jetpack Compose în PNG fără emulator. Folosește Layoutlib (același motor ca Android Studio Preview). Configurare: conectarea pluginului Gradle, scrierea testului cu @Test și @RunWith(PaparazziRule::class), apelarea paparazzi.snapshot(view). Paparazzi nu suportă animații, video și Real Device — doar randare statică a componentelor.

kotlin
// build.gradle.kts (module)
plugins {
    id("app.cash.paparazzi") version "1.3.1"
}

// Golden test pentru componenta Compose
class ButtonGoldenTest {

    @get:Rule
    val paparazzi = Paparazzi(
        Paparazzi.PaparazziSnapshotConfig(
            deviceConfig = DeviceConfig.PIXEL_6,
            theme = "android:Theme.Material.Light.NoActionBar"
        )
    )

    @Test
    fun primary_button() {
        paparazzi.snapshot {
            Button(
                onClick = { },
                modifier = Modifier.width(200.dp)
            ) {
                Text("Submit")
            }
        }
    }
}

Roborazzi — alternativă la Paparazzi cu suport pentru Compose, View și compararea imaginilor. Diferența: Roborazzi funcționează prin Robolectric și suportă threshold (procentul de diferență admisibilă a pixelilor). Aceasta reduce flakiness-ul la GPU diferite pe CI. Roborazzi poate crea și animații GIF ale modificărilor (înainte/după/diff), ceea ce este convenabil pentru revizuirea codului. Formatul fișierelor golden: PNG + metadate JSON.

Actualizarea golden — după o modificare intenționată a UI, dezvoltatorul șterge fișierele golden vechi și rulează testurile cu flagul record. Paparazzi creează din nou toate fișierele golden. Apoi dezvoltatorul commit-uiește noul golden împreună cu modificarea codului. În revizuirea codului, recenzentul vede diff-ul golden-urilor vechi și noi. Dacă modificările sunt aprobate — PR-ul este îmbinat. Dacă nu — dezvoltatorul corectează codul și rulează din nou testurile. Nu actualizați niciodată golden automat pe CI — doar local.

SwiftSnapshotTesting și iOSSnapshotTestCase pe iOS

SwiftSnapshotTesting — bibliotecă de la pointfree.co, creatorii Composable Architecture. Suportă UIView, UIViewController, CALayer și SwiftUI View. Principiu: assertSnapshot(matching: view, as: .image). La prima rulare, golden este creat automat. La următoarele — este comparat. Dacă diferența depășește limita admisibilă — testul eșuează. SwiftSnapshotTesting funcționează prin UIGraphicsImageRenderer, care este compatibil cu CI (Xcode Cloud, GitHub Actions).

swift
import SnapshotTesting
import XCTest

final class ProfileCardSnapshotTests: XCTestCase {

    func test_profile_card_default() {
        let card = ProfileCard(
            name: "Alice",
            avatar: UIImage.testImage(),
            badge: "Pro"
        )
        let controller = UIHostingController(rootView: card)

        assertSnapshot(
            matching: controller,
            as: .image(on: .iPhoneSe),
            record: ProcessInfo.processInfo
                .environment["RECORD"] != nil
        )
    }
}

iOSSnapshotTestCase (fost FBSnapshotTestCase) — bibliotecă de la Uber pentru UIKit. Spre deosebire de SwiftSnapshotTesting, iOSSnapshotTestCase necesită specificarea dimensiunii ecranului și orientării. Fișierele golden — PNG în folderul ReferenceImages. Avantaj: funcționează cu UIKit fără SwiftUI și suportă iOS 12+. Dezavantaj: nu actualizează golden automat — trebuie rulat cu flagul record. SwiftSnapshotTesting este mai modern și recomandat pentru proiecte noi.

Golden specific dispozitivului — fișierele golden diferă pentru diferite dimensiuni de ecran și orientări. Abordarea standard: denumirea golden ca TestName@3x~iPhone14.png. SwiftSnapshotTesting adaugă automat sufixul dispozitivului dacă este dat parametrul .image(on: .iPhoneSe). Pe Android, Paparazzi folosește DeviceConfig pentru setarea dimensiunii. Stocați golden pentru fiecare form factor de dispozitiv suportat separat. Nu folosiți un singur golden pentru dimensiuni diferite — aceasta va duce la teste flaky.

Lucrul cu fișierele golden în CI și gestionarea actualizărilor

Pipeline CI — golden-testurile ar trebui să ruleze la fiecare Pull Request. Dacă testul eșuează, CI arată imaginea diff ca artefact de construire. Dezvoltatorul verifică diff-ul și ia o decizie. Important: fișierele golden generate pe CI nu sunt niciodată comițate automat. Doar generare locală de către dezvoltator după o modificare intenționată. GitHub Actions și GitLab CI suportă încărcarea artefactelor (png, html) pentru vizualizarea diff-ului în browser.

Dimensiunea depozitului — fișierele golden cresc rapid. 500 de teste = 100-400 MB PNG. Soluții: (1) Git LFS — fiecare golden este stocat în LFS, clonat doar la checkout. (2) Stocarea golden într-un depozit separat și conectarea ca submodul. (3) S3 + memorare în cache — golden pe S3, CI descarcă doar fișierele modificate după checksum. În IT Sectr folosim Git LFS cu track *.png filter=lfs diff=lfs merge=lfs text=false. Local, golden se află în src/test/goldens/.

Revizuirea codului golden — git diff obișnuit nu arată modificările PNG. Soluții: (1) GitHub deschide imaginile PNG la clic. (2) Utilizarea Review Apps, unde golden-diff este vizibil în browser. (3) Generarea unui raport HTML cu coloanele înainte/după/diff. Paparazzi creează un raport HTML cu trei coloane: actual, expected, diff. Raportul este atașat la artefactele CI. Recenzorii verifică raportul fără a descărca fișierele local.

Când să actualizați golden — doar după o modificare conștientă a UI. Modificarea fontului, culorii, spațierii, pictogramei — golden trebuie actualizat. Adăugarea unui buton nou, rearanjarea elementelor — golden trebuie actualizat. Corectarea unei erori care schimbă aspectul — golden trebuie actualizat. Refactorizarea fără modificarea UI — golden nu trebuie actualizat. Dacă golden se modifică fără modificarea codului UI — este un test flaky cauzat de mediu, căutați cauza în agenții CI sau versiunile dependențelor.

Întrebări frecvente

Cu ce se deosebește Golden Test de Screenshot Test?

Golden Test — snapshot-test la nivel de componentă în mediul unit-test (rapid, fără emulator). Screenshot Test — capturarea întregului ecran pe dispozitiv sau emulator (lent, dar realist). Golden funcționează cu buffer în afara ecranului, screenshot — cu afișajul real. Golden este potrivit pentru CI la fiecare commit, screenshot — pentru rulări nightly înainte de lansare.

Cum să combatem testele flaky golden?

Cauze principale: (1) GPU diferite pe CI — utilizați agenți CI identici. (2) Versiuni diferite de fonturi — fixați versiunea OS. (3) Anti-aliasing diferit — configurați threshold (Roborazzi, iOSSnapshotTestCase). (4) Animații — dezactivați animațiile în teste. (5) Elemente de sistem (bara de stare) — utilizați config fără ramă. Paparazzi nu este susceptibil la flakiness datorită Layoutlib.

Se poate folosi Golden Test cu Jetpack Compose?

Da. Paparazzi are suport încorporat pentru Compose prin paparazzi.snapshot { }. Roborazzi suportă de asemenea Compose. În iOS, SwiftSnapshotTesting funcționează cu SwiftUI prin UIHostingController. Componentele Compose sunt randate prin Layoutlib, SwiftUI — prin randarea UIKit. Limitare: animațiile Compose și SwiftUI nu sunt suportate — golden-testul capturează doar starea inițială.

Cum să acceptăm automat modificările golden?

Nu automatizați niciodată acceptarea golden pe CI. Doar local: dezvoltatorul șterge fișierele golden vechi din director și rulează testurile cu flagul record (Paparazzi: record=true, SwiftSnapshotTesting: record=true). Fișierele golden sunt recreate. Dezvoltatorul verifică fiecare golden pentru corectitudine, commit-uiește modificările împreună cu codul. Acceptarea automată pe CI va duce la trecerea cu vederea a erorilor UI.

Încetinește Golden Test construirea?

Golden-testurile sunt mai rapide decât testele instrumentale (UI Automator, XCUITest). Un golden-test se execută în 50-200 ms (Paparazzi: 100-150 ms pe un MacBook Pro mediu). 500 golden-testuri = 25-100 secunde. Comparați cu screenshot-testurile prin emulator: 5-30 secunde per test. Golden-testurile nu încetinesc construirea: 100 de teste = ~15 secunde, ceea ce este acceptabil pentru verificarea pre-merge.

Concluzii

  • Golden Test — testarea vizuală a componentelor UI prin compararea cu imaginea etalon PNG
  • Proces — randarea componentei în buffer în afara ecranului, comparare pixel cu pixel, diff la nepotrivire
  • Android — Paparazzi (Compose/View, Layoutlib) și Roborazzi (Compose/View, threshold, Robolectric)
  • iOS — SwiftSnapshotTesting (pointfree) și iOSSnapshotTestCase de la Uber pentru UIKit și SwiftUI
  • Pipeline CI — golden-testuri la fiecare PR, artefacte diff, doar actualizare locală a golden
  • Git LFS — obligatoriu pentru stocarea fișierelor PNG (100-400 MB pentru 500 de teste)
  • Flakiness — legat de GPU, fonturi și anti-aliasing; rezolvat prin threshold și agenți CI identici

Vom dezvolta o aplicație mobilă la cheie

IT Sectr creează aplicații iOS și Android pentru startup-uri și afaceri din 2017. Vă vom consilia și vă vom propune cea mai bună soluție.

Discutați proiectul

Citiți și