Golden Test — mi ez, hogyan működik a snapshot-tesztelés és alkalmazása

Szerző: IT Sectr Megjelenés: 2026-04-10 Olvasási idő: 9 perc

Golden Test (snapshot-test, referenciatesztelés) — a UI vizuális tesztelésének módszere, amelyben a komponens aktuális renderelése egy előre elmentett referenciaképhez (golden-fájl) hasonlít. Ha a pixelváltozások meghaladják a beállított küszöbértéket, a teszt sikertelen lesz és diff-képet generál. A fejlesztő megtekinti a diff-et és vagy elfogadja a változtatásokat (frissíti a golden-t), vagy kijavítja a hibát. Bővebben a Meta Engineering cikkében a Paparazziról.

Főbb pontok

  • Golden Test — az aktuális UI összehasonlítása a referenciaképpel a vizuális regressziók észleléséhez
  • Diff-kép — eltérés esetén a golden-test diff-et generál a megváltozott pixelek kiemelésével
  • Android — Paparazzi és Roborazzi a compose és view komponensek screenshot-teszteléséhez
  • iOS — SwiftSnapshotTesting (pointfree.co) és iOSSnapshotTestCase az Uber-től SwiftUI és UIKit számára
  • CI-integráció — a golden-tesztek CI-n futnak és váratlan UI-változásoknál sikertelenek

Mi a Golden Test és hogyan működik?

Golden Test — a komponens megjelenésének automatizált ellenőrzése pixelről-pixelre történő összehasonlítással a referenciával. Folyamat: (1) a fejlesztő vagy tesztelő elkészíti a komponens első felvételét — ez a “golden” (referencia). (2) A golden-fájl a teszt mellett a repository-ban kerül elmentésre. (3) A későbbi futtatások során a teszt újra rendereli a komponenst és összehasonlítja az elmentett golden-nel. (4) Ha a képek egyeznek — a teszt zöld. Ha eltérnek — a teszt piros diff-fel. Döntés: vagy a változtatások várhatóak (frissítjük a golden-t), vagy ez egy hiba.

Hogyan generálódik a golden — a könyvtár a komponenst egy off-screen pufferben rendereli (Android: Canvas, iOS: UIGraphicsImageRenderer) valódi kijelző nélkül. Ez azt jelenti, hogy a golden-tesztek CI-n működnek képernyő-emulátor (virtual display) nélkül, ami felgyorsítja a végrehajtást. A Paparazzi Androidon az Android Studio Layoutlib-jét használja — ugyanazt a motort, mint a Layout Editor. Az iOSSnapshotTestCase UIKit-renderelést használ CGImage-be. Eredmény — egy rögzített méretű PNG fájl.

A golden-fájlok mérete és tároláskezelés

Golden-fájlok — egy képernyő PNG felvétele (1080x1920) 200-800 KB-ot foglal a komplexitástól függően. Egy 500 golden-teszttel rendelkező projekt esetén ez ~100-400 MB a repository-ban. Megoldások: (1) golden tárolása Git LFS-ben. (2) PNG tömörítés használata (pngcrush, oxipng). (3) Golden tárolása külön tárhelyen (S3) és letöltés build-kor. Az IT Sectr-nél golden-t Git LFS-ben tárolunk 1 MB fájlonkénti küszöbértékkel — ez a tesztek 90%-ához elegendő.

Flaky golden tesztek és megoldásuk

Flaky golden tesztek — a golden-tesztek fő problémája. Különböző GPU-k, betűtípus-verziók és anti-aliasing mikro-eltéréseket okoznak a pixelekben. Megoldások: threshold (eltérő pixelek megengedett százaléka), fuzzy comparison (elmosódott összehasonlítás) és azonos CI-ügynökökön történő futtatás (azonos GPU, OS, emulátorverzió). A Paparazzi pixel-perfect összehasonlítást használ, ezért a CI-ügynököknek azonosnak kell lenniük.

Golden Test vs Screenshot Test: mi a különbség?

Golden Test — a screenshot-tesztelés egy fajtája rögzített referenciával. A “golden” kifejezés azt jelenti, hogy a referenciát a csapat jóváhagyta (elfogadta) és a repository-ban tárolja. A kép bármilyen változása a fejlesztő tudatos döntését igényli: a golden frissítése vagy a kód javítása. A Golden Test egyes komponensek szintjén működik (Composable, UIView) és nem igényel valódi eszközt.

Screenshot Test — tágabb fogalom. A Screenshot-test a teljes képernyőt rögzítheti valódi adatokkal, navigációval, rendszer állapotsorral és animációkkal. A Screenshot-tesztek gyakran valódi eszközökön vagy emulátorokon futnak UI Automator (Android) vagy XCUITest (iOS) segítségével. A Golden-tesztek unit-test környezetben (JVM, XCTest) működnek emulátor nélkül és csak egy komponenst rögzítenek.

JellemzőGolden TestScreenshot Test
SzintKomponens/Composable/ViewTeljes képernyő
KörnyezetUnit-test (off-screen puffer)Eszköz/Emulátor
Sebesség50-200 ms tesztenként2-30 másodperc tesztenként
AnimációkNem támogatottakTámogatottak (szünetekkel)
CI GPU nélkülMűködik (Layoutlib)Emulátort igényel
Beállítás bonyolultságaAlacsonyMagas (Emulátor/Device Farm)
FlakinessKözepes (különböző GPU)Magas (emulátor, idő)

Lefedettségi stratégia: golden vs screenshot

Golden vs Screenshot — golden-tesztek az egyes UI-komponensek (gomb, kártya, párbeszédablak) ellenőrzésére minden commit-nál. Screenshot-tesztek — a teljes képernyők E2E ellenőrzésére kiadás előtt. A golden-tesztek gyors visszajelzést adnak a fejlesztőnek, a screenshot-tesztek — bizalmat a teljes alkalmazás integritásában. Az IT Sectr-nél golden-teszteket használunk Pull Request-hez (3-5 perc), screenshot-teszteket — nightly futtatásokhoz (30-60 perc).

Paparazzi és Roborazzi: snapshot-tesztelés Androidon

Paparazzi — a Cash App (Square) könyvtára, amely Android View és Jetpack Compose komponenseket renderel PNG-be emulátor nélkül. A Layoutlib-et használja (ugyanaz a motor, mint az Android Studio Preview). Beállítás: Gradle plugin csatlakoztatása, teszt írása @Test és @RunWith(PaparazziRule::class) paranccsal, paparazzi.snapshot(view) meghívása. A Paparazzi nem támogatja az animációkat, videót és Real Device-t — csak statikus komponens-renderelést.

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

// Golden test a Compose-komponenshez
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 — a Paparazzi alternatívája Compose, View és képek összehasonlításának támogatásával. Különbség: a Roborazzi Robolectric-en keresztül működik és támogatja a threshold-t (megengedett pixelkülönbség százaléka). Ez csökkenti a flakiness-t különböző GPU-k esetén CI-n. A Roborazzi képes GIF-animációkat is készíteni a változásokról (előtte/utána/diff), ami kényelmes a kód áttekintéséhez. A golden-fájlok formátuma: PNG + JSON metaadatok.

Golden frissítése — a UI szándékos megváltoztatása után a fejlesztő törli a régi golden-fájlokat és record flag-gel futtatja a teszteket. A Paparazzi újra létrehozza az összes golden-fájlt. Ezután a fejlesztő commit-eli az új golden-t a kódváltoztatással együtt. A kód áttekintése során a bíráló látja a régi és új golden-ek diff-jét. Ha a változtatások jóvá vannak hagyva — a PR egyesítésre kerül. Ha nem — a fejlesztő kijavítja a kódot és újra futtatja a teszteket. Soha ne frissítse a golden-t automatikusan CI-n — csak lokálisan.

SwiftSnapshotTesting és iOSSnapshotTestCase iOS-en

SwiftSnapshotTesting — a pointfree.co könyvtára, a Composable Architecture alkotói. Támogatja a UIView, UIViewController, CALayer és SwiftUI View típusokat. Elv: assertSnapshot(matching: view, as: .image). Az első futtatáskor a golden automatikusan létrejön. A következőknél — összehasonlításra kerül. Ha a különbség meghaladja a megengedettet — a teszt sikertelen. A SwiftSnapshotTesting a UIGraphicsImageRenderer-en keresztül működik, amely kompatibilis a CI-vel (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 (korábban FBSnapshotTestCase) — az Uber könyvtára UIKit számára. A SwiftSnapshotTesting-től eltérően az iOSSnapshotTestCase megköveteli a képernyő méretének és tájolásának megadását. Golden-fájlok — PNG a ReferenceImages mappában. Előny: UIKit-kel működik SwiftUI nélkül és támogatja az iOS 12+-t. Hátrány: nem frissíti automatikusan a golden-t — record flag-gel kell futtatni. A SwiftSnapshotTesting modernebb és új projektekhez ajánlott.

Eszközspecifikus golden — a golden-fájlok eltérőek a különböző képernyőméretek és tájolások esetén. Szabványos megközelítés: a golden elnevezése TestName@3x~iPhone14.png formátumban. A SwiftSnapshotTesting automatikusan hozzáadja az eszköz utótagot, ha az .image(on: .iPhoneSe) paraméter meg van adva. Androidon a Paparazzi a DeviceConfig-ot használja a méret beállításához. Tárolja a golden-t minden támogatott eszköz form faktorhoz külön. Ne használjon egy golden-t különböző méretekhez — ez flaky tesztekhez vezet.

Golden-fájlok használata CI-ben és frissítések kezelése

CI pipeline — a golden-teszteket minden Pull Request-nél futtatni kell. Ha a teszt sikertelen, a CI megjeleníti a diff-képet build műtermékként. A fejlesztő megtekinti a diff-et és döntést hoz. Fontos: a CI-n generált golden-fájlok soha nem kerülnek automatikus commit-ra. Csak a fejlesztő általi lokális generálás szándékos változtatás után. A GitHub Actions és a GitLab CI támogatja a műtermékek (png, html) feltöltését a diff böngészőben történő megtekintéséhez.

Repository mérete — a golden-fájlok gyorsan nőnek. 500 teszt = 100-400 MB PNG. Megoldások: (1) Git LFS — minden golden LFS-ben tárolva, csak checkout-kor klónozva. (2) Golden tárolása külön repository-ban és almodulként csatlakoztatva. (3) S3 + gyorsítótárazás — golden az S3-on, a CI csak a checksum alapján módosított fájlokat tölti le. Az IT Sectr-nél Git LFS-t használunk track *.png filter=lfs diff=lfs merge=lfs text=false beállítással. Lokálisan a golden-ek a src/test/goldens/ mappában találhatók.

Golden kód áttekintése — a szokásos git diff nem mutatja a PNG-változásokat. Megoldások: (1) A GitHub megnyitja a PNG-képeket kattintásra. (2) Review Apps használata, ahol a golden-diff látható a böngészőben. (3) HTML-jelentés generálása előtte/utána/diff oszlopokkal. A Paparazzi három oszlopos HTML-jelentést készít: actual, expected, diff. A jelentés a CI-műtermékekhez csatolódik. A bírálók a jelentést a fájlok lokális letöltése nélkül tekintik meg.

Mikor frissítsük a golden-t — csak a UI tudatos megváltoztatása után. Betűtípus, szín, térköz, ikon változása — a golden-t frissíteni kell. Új gomb hozzáadása, elemek átrendezése — a golden-t frissíteni kell. Hibajavítás, amely megváltoztatja a megjelenést — a golden-t frissíteni kell. Refaktorálás UI-változtatás nélkül — a golden-t nem kell frissíteni. Ha a golden UI-kód változtatása nélkül változik — ez egy flaky teszt, amelyet a környezet okoz, keresse az okot a CI-ügynökökben vagy a függőségi verziókban.

Gyakran ismételt kérdések

Miben különbözik a Golden Test a Screenshot Test-től?

Golden Test — snapshot-test komponens szinten unit-test környezetben (gyors, emulátor nélkül). Screenshot Test — a teljes képernyő rögzítése eszközön vagy emulátoron (lassú, de valósághű). A golden off-screen pufferrel működik, a screenshot — valódi kijelzővel. A golden minden commit-nál CI-re alkalmas, a screenshot — nightly futtatásokra kiadás előtt.

Hogyan kezeljük a flaky golden teszteket?

Fő okok: (1) Különböző GPU-k CI-n — használjon azonos CI-ügynököket. (2) Különböző betűtípus-verziók — rögzítse az OS verzióját. (3) Különböző anti-aliasing — állítsa be a threshold-t (Roborazzi, iOSSnapshotTestCase). (4) Animációk — kapcsolja ki az animációkat a tesztekben. (5) Rendszerelemek (állapotsor) — használjon keret nélküli device config-ot. A Paparazzi nem érzékeny a flakiness-re a Layoutlib miatt.

Használható a Golden Test Jetpack Compose-zal?

Igen. A Paparazzi beépített támogatással rendelkezik a Compose-hoz a paparazzi.snapshot { } segítségével. A Roborazzi szintén támogatja a Compose-t. iOS-en a SwiftSnapshotTesting a SwiftUI-val működik a UIHostingController-en keresztül. A Compose-komponensek a Layoutlib-en keresztül, a SwiftUI — UIKit-rendereléssel jelenik meg. Korlátozás: a Compose és SwiftUI animációk nem támogatottak — a golden-test csak a kezdeti állapotot rögzíti.

Hogyan fogadjuk el automatikusan a golden változásait?

Soha ne automatizálja a golden elfogadását CI-n. Csak lokálisan: a fejlesztő törli a régi golden-fájlokat a könyvtárból és record flag-gel futtatja a teszteket (Paparazzi: record=true, SwiftSnapshotTesting: record=true). A golden-fájlok újra létrejönnek. A fejlesztő ellenőrzi minden golden helyességét, commit-eli a változtatásokat a kóddal együtt. Az automatikus elfogadás CI-n UI-hibák kihagyásához vezet.

Lassítja-e a Golden Test a build-et?

A golden-tesztek gyorsabbak, mint az instrumentális tesztek (UI Automator, XCUITest). Egy golden-test 50-200 ms alatt fut le (Paparazzi: 100-150 ms egy átlagos MacBook Pro-n). 500 golden-test = 25-100 másodperc. Hasonlítsa össze az emulátoros screenshot-tesztekkel: 5-30 másodperc tesztenként. A golden-tesztek nem lassítják a build-et: 100 teszt = ~15 másodperc, ami elfogadható a pre-merge ellenőrzéshez.

Összefoglalás

  • Golden Test — UI-komponensek vizuális tesztelése referenciaképpel való összehasonlítással
  • Folyamat — komponens renderelése off-screen pufferben, pixelről-pixelre összehasonlítás, diff eltérés esetén
  • Android — Paparazzi (Compose/View, Layoutlib) és Roborazzi (Compose/View, threshold, Robolectric)
  • iOS — SwiftSnapshotTesting (pointfree) és iOSSnapshotTestCase az Uber-től UIKit és SwiftUI számára
  • CI Pipeline — golden-tesztek minden PR-nél, diff műtermékek, csak lokális golden frissítés
  • Git LFS — kötelező a PNG-fájlok tárolásához (100-400 MB 500 teszthez)
  • Flakiness — GPU-hoz, betűtípusokhoz és anti-aliasing-hoz kapcsolódó; threshold és azonos CI-ügynökök oldják meg

Kulcsrakész mobilalkalmazást fejlesztünk

Az IT Sectr 2017 óta készít iOS és Android alkalmazásokat induló vállalkozásoknak és vállalkozásoknak. Tanácsot adunk, és a legjobb megoldást javasoljuk.

Projekt megbeszélése

Olvassa el is