Golden Test (snapshot-test, referenstestning) — metod för visuell testning av UI där den aktuella renderingen av en komponent jämförs med en förhands sparad referensbild (golden-fil). Om pixeländringar överskrider ett inställt tröskelvärde misslyckas testet och genererar en diff-bild. Utvecklaren granskar diffen och antingen accepterar ändringarna (uppdaterar golden) eller åtgärdar felet. Mer i Meta Engineerings artikel om Paparazzi.
Huvudpunkter
Golden Test — är en automatiserad kontroll av komponentens utseende genom pixel-för-pixel jämförelse med referensen. Process: (1) utvecklaren eller testaren tar den första skärmbilden av komponenten — detta är “golden” (referensen). (2) Golden-filen sparas i repositoryt bredvid testet. (3) Vid efterföljande körningar renderar testet komponenten igen och jämför med den sparade golden. (4) Om bilderna matchar — är testet grönt. Om de skiljer sig — är testet rött med diff. Beslut: antingen är ändringarna förväntade (vi uppdaterar golden) eller så är det ett fel.
Hur golden genereras — biblioteket renderar komponenten i en off-screen buffer (Android: Canvas, iOS: UIGraphicsImageRenderer) utan verklig skärm. Detta innebär att golden-tester fungerar på CI utan skärmemulator (virtual display), vilket påskyndar exekveringen. Paparazzi på Android använder Layoutlib från Android Studio — samma motor som Layout Editor. iOSSnapshotTestCase använder UIKit-rendering till CGImage. Resultat — en PNG-fil med fast storlek.
Golden-filer — en PNG-skärmbild av en skärm (1080x1920) tar 200-800 KB beroende på komplexitet. För ett projekt med 500 golden-tester är detta ~100-400 MB i repositoryt. Lösningar: (1) lagra golden i Git LFS. (2) Använda PNG-komprimering (pngcrush, oxipng). (3) Lagra golden i separat lagring (S3) och hämta vid bygge. På IT Sectr lagrar vi golden i Git LFS med ett tröskelvärde på 1 MB per fil — detta räcker för 90% av testerna.
Flaky golden-tester — huvudproblemet med golden-tester. Olika GPU:er, teckensnittsversioner och kantutjämning ger mikro-skillnader i pixlar. Lösningar: threshold (tillåten procentandel olika pixlar), fuzzy comparison (suddig jämförelse) och körning på identiska CI-agenter (samma GPU, OS, emulatorversion). I Paparazzi används pixel-perfect jämförelse, därför måste CI-agenterna vara identiska.
Golden Test — är en typ av screenshot-testning med fast referens. Termen “golden” betyder att referensen har godkänts (accepterats) av teamet och lagras i repositoryt. Varje ändring av bilden kräver ett medvetet beslut av utvecklaren: uppdatera golden eller korrigera koden. Golden Test fungerar på nivån av enskilda komponenter (Composable, UIView) och kräver ingen verklig enhet.
Screenshot Test — ett bredare begrepp. Screenshot-test kan fånga hela skärmen med verklig data, navigering, systemstatusfält och animeringar. Screenshot-tester körs ofta på verkliga enheter eller emulatorer via UI Automator (Android) eller XCUITest (iOS). Golden-tester fungerar i unit-test miljö (JVM, XCTest) utan emulator och fångar endast en enskild komponent.
| Egenskap | Golden Test | Screenshot Test |
|---|---|---|
| Nivå | Komponent/Composable/View | Hela skärmen |
| Miljö | Unit-test (off-screen buffer) | Enhet/Emulator |
| Hastighet | 50-200 ms per test | 2-30 sekunder per test |
| Animeringar | Stöds inte | Stöds (med pauser) |
| CI utan GPU | Fungerar (Layoutlib) | Kräver emulator |
| Konfigurationskomplexitet | Låg | Hög (Emulator/Device Farm) |
| Flakiness | Medel (olika GPU) | Hög (emulator, tid) |
Golden vs Screenshot — golden-tester för att kontrollera enskilda UI-komponenter (knapp, kort, dialog) vid varje commit. Screenshot-tester — för E2E-kontroll av hela skärmar före release. Golden-tester ger snabb återkoppling till utvecklaren, screenshot-tester — förtroende för hela applikationens integritet. På IT Sectr använder vi golden-tester för Pull Request (3-5 minuter) och screenshot-tester för nightly (30-60 minuter).
Paparazzi — bibliotek från Cash App (Square) som renderar Android View och Jetpack Compose-komponenter till PNG utan emulator. Använder Layoutlib (samma motor som Android Studio Preview). Konfiguration: ansluta Gradle-plugin, skriva test med @Test och @RunWith(PaparazziRule::class), anropa paparazzi.snapshot(view). Paparazzi stöder inte animeringar, video och Real Device — endast statisk rendering av komponenter.
// build.gradle.kts (module)
plugins {
id("app.cash.paparazzi") version "1.3.1"
}
// Golden test för Compose-komponent
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 till Paparazzi med stöd för Compose, View och bildjämförelse. Skillnad: Roborazzi fungerar via Robolectric och stöder threshold (procentandel tillåten pixelskillnad). Detta minskar flakiness vid olika GPU:er på CI. Roborazzi kan också skapa GIF-animeringar av ändringar (före/efter/diff), vilket är praktiskt för kodgranskning. Format på golden-filer: PNG + JSON-metadata.
Uppdatering av golden — efter en avsiktlig UI-ändring tar utvecklaren bort gamla golden-filer och kör testerna med record-flagga. Paparazzi återskapar alla golden-filer. Därefter commitar utvecklaren den nya golden tillsammans med kodändringen. Vid kodgranskning ser granskaren diffen av gamla och nya golden. Om ändringarna godkänns — slås PR:n ihop. Om inte — korrigerar utvecklaren koden och kör testerna igen. Uppdatera aldrig golden automatiskt på CI — endast lokalt.
SwiftSnapshotTesting — bibliotek från pointfree.co, skapare av Composable Architecture. Stöder UIView, UIViewController, CALayer och SwiftUI View. Princip: assertSnapshot(matching: view, as: .image). Vid första körningen skapas golden automatiskt. Vid efterföljande — jämförs. Om skillnaden överskrider tillåten gräns — misslyckas testet. SwiftSnapshotTesting fungerar via UIGraphicsImageRenderer, som är kompatibelt med CI (Xcode Cloud, GitHub Actions).
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 (tidigare FBSnapshotTestCase) — bibliotek från Uber för UIKit. Till skillnad från SwiftSnapshotTesting kräver iOSSnapshotTestCase att skärmstorlek och orientering specificeras. Golden-filer — PNG i mappen ReferenceImages. Fördel: fungerar med UIKit utan SwiftUI och stöder iOS 12+. Nackdel: uppdaterar inte golden automatiskt — måste köras med record-flagga. SwiftSnapshotTesting är modernare och rekommenderas för nya projekt.
Enhetsspecifik golden — golden-filer skiljer sig för olika skärmstorlekar och orienteringar. Standardmetod: namnge golden som TestName@3x~iPhone14.png. SwiftSnapshotTesting lägger automatiskt till enhetssuffix om parametern .image(on: .iPhoneSe) anges. På Android använder Paparazzi DeviceConfig för att ställa in storlek. Förvara golden för varje enhetsformfaktor separat. Använd inte en golden för olika storlekar — detta leder till flaky tester.
CI pipeline — golden-tester bör köras vid varje Pull Request. Om testet misslyckas visar CI diff-bilden som byggartefakt. Utvecklaren granskar diffen och fattar beslut. Viktigt: golden-filer genererade på CI committas aldrig automatiskt. Endast lokal generering av utvecklaren efter avsiktlig ändring. GitHub Actions och GitLab CI stöder uppladdning av artefakter (png, html) för att visa diff i webbläsaren.
Repositorystorlek — golden-filer växer snabbt. 500 tester = 100-400 MB PNG. Lösningar: (1) Git LFS — varje golden lagras i LFS, klonas endast vid checkout. (2) Lagra golden i separat repository och anslut som submodul. (3) S3 + cachning — golden på S3, CI laddar endast ned ändrade filer baserat på checksumma. På IT Sectr använder vi Git LFS med track *.png filter=lfs diff=lfs merge=lfs text=false. Lokalt ligger golden i src/test/goldens/.
Kodgranskning av golden — vanlig git diff visar inte PNG-ändringar. Lösningar: (1) GitHub öppnar PNG-bilder vid klick. (2) Använda Review Apps, där golden-diff är synlig i webbläsaren. (3) Generera HTML-rapport med kolumner före/efter/diff. Paparazzi skapar en HTML-rapport med tre kolumner: actual, expected, diff. Rapporten bifogas till CI-artefakter. Granskare ser rapporten utan att ladda ned filer lokalt.
När ska golden uppdateras — endast efter en medveten UI-ändring. Ändring av teckensnitt, färg, avstånd, ikon — golden bör uppdateras. Tillägg av ny knapp, omarrangering av element — golden bör uppdateras. Felkorrigering som ändrar utseendet — golden bör uppdateras. Refaktorisering utan UI-ändring — golden bör inte uppdateras. Om golden ändras utan UI-kodändring — är detta ett flaky test orsakat av miljön, sök orsaken i CI-agenter eller beroendeversioner.
Vanliga frågor
Golden Test — snapshot-test på komponentnivå i unit-test miljö (snabbt, utan emulator). Screenshot Test — fånga hela skärmen på enhet eller emulator (långsamt, men realistiskt). Golden arbetar med off-screen buffer, screenshot — med verklig skärm. Golden passar för CI vid varje commit, screenshot — för nightly före release.
Huvudorsaker: (1) Olika GPU:er på CI — använd identiska CI-agenter. (2) Olika teckensnittsversioner — fixera OS-versionen. (3) Olika kantutjämning — konfigurera threshold (Roborazzi, iOSSnapshotTestCase). (4) Animeringar — stäng av animeringar i tester. (5) Systemelement (statusfält) — använd ramlös device config. Paparazzi är inte mottagligt för flakiness på grund av Layoutlib.
Ja. Paparazzi har inbyggt stöd för Compose via paparazzi.snapshot { }. Roborazzi stöder också Compose. På iOS fungerar SwiftSnapshotTesting med SwiftUI via UIHostingController. Compose-komponenter renderas via Layoutlib, SwiftUI — via UIKit-rendering. Begränsning: Compose- och SwiftUI-animeringar stöds inte — golden-test fångar endast starttillståndet.
Automatisera aldrig golden-acceptans på CI. Endast lokalt: utvecklaren tar bort gamla golden-filer från katalogen och kör testerna med record-flagga (Paparazzi: record=true, SwiftSnapshotTesting: record=true). Golden-filer återskapas. Utvecklaren kontrollerar varje golden för korrekthet, commitar ändringarna tillsammans med koden. Automatisk acceptans på CI leder till att UI-fel missas.
Golden-tester är snabbare än instrumentella tester (UI Automator, XCUITest). Ett golden-test körs på 50-200 ms (Paparazzi: 100-150 ms på en genomsnittlig MacBook Pro). 500 golden-tester = 25-100 sekunder. Jämför med screenshot-tester via emulator: 5-30 sekunder per test. Golden-tester saktar inte ner bygget: 100 tester = ~15 sekunder, vilket är acceptabelt för pre-merge-verifiering.
Sammanfattning
Vi utvecklar en mobil applikation nyckelfärdigt
IT Sectr skapar iOS- och Android-applikationer för startups och företag sedan 2017. Vi ger dig råd och föreslår den bästa lösningen.
Läs också