Golden Test — τι είναι, πώς λειτουργεί το snapshot-testing και εφαρμογή

Συγγραφέας: IT Sectr Δημοσιεύτηκε: 2026-04-10 Χρόνος ανάγνωσης: 9 λεπ

Golden Test (snapshot-test, δοκιμή προτύπου) — μέθοδος οπτικής δοκιμής UI κατά την οποία η τρέχουσα απόδοση του στοιχείου συγκρίνεται με μια προαποθηκευμένη εικόνα προτύπου (golden-αρχείο). Εάν οι αλλαγές pixel υπερβούν το καθορισμένο όριο, η δοκιμή αποτυγχάνει και δημιουργεί μια εικόνα diff. Ο προγραμματιστής εξετάζει το diff και είτε αποδέχεται τις αλλαγές (ενημερώνει το golden) είτε διορθώνει το σφάλμα. Περισσότερα στο άρθρο του Meta Engineering για το Paparazzi.

Κύρια σημεία

  • Golden Test — σύγκριση του τρέχοντος UI με την εικόνα προτύπου για ανίχνευση οπτικών παλινδρομήσεων
  • Εικόνα diff — σε περίπτωση ασυμφωνίας, το golden-test δημιουργεί diff με επισήμανση των αλλαγμένων pixel
  • Android — Paparazzi και Roborazzi για screenshot-testing στοιχείων compose και view
  • iOS — SwiftSnapshotTesting (pointfree.co) και iOSSnapshotTestCase από την Uber για SwiftUI και UIKit
  • Ενσωμάτωση CI — τα golden-test εκτελούνται στο CI και αποτυγχάνουν σε απροσδόκητες αλλαγές UI

Τι είναι το Golden Test και πώς λειτουργεί;

Golden Test — είναι ένας αυτοματοποιημένος έλεγχος της εμφάνισης του στοιχείου μέσω σύγκρισης pixel προς pixel με το πρότυπο. Διαδικασία: (1) ο προγραμματιστής ή ο ελεγκτής λαμβάνει το πρώτο στιγμιότυπο του στοιχείου — αυτό είναι το “golden” (πρότυπο). (2) Το golden-αρχείο αποθηκεύεται στο αποθετήριο δίπλα στη δοκιμή. (3) Σε επόμενες εκτελέσεις, η δοκιμή αποδίδει ξανά το στοιχείο και το συγκρίνει με το αποθηκευμένο golden. (4) Εάν οι εικόνες ταιριάζουν — η δοκιμή είναι πράσινη. Εάν διαφέρουν — η δοκιμή είναι κόκκινη με diff. Απόφαση: είτε οι αλλαγές είναι αναμενόμενες (ενημερώνουμε το golden) είτε είναι σφάλμα.

Πώς δημιουργείται το golden — η βιβλιοθήκη αποδίδει το στοιχείο σε προσωρινή μνήμη εκτός οθόνης (Android: Canvas, iOS: UIGraphicsImageRenderer) χωρίς πραγματική οθόνη. Αυτό σημαίνει ότι τα golden-test λειτουργούν στο CI χωρίς εξομοιωτή οθόνης (virtual display), γεγονός που επιταχύνει την εκτέλεση. Το Paparazzi στο Android χρησιμοποιεί το Layoutlib από το Android Studio — τον ίδιο κινητήρα με το Layout Editor. Το iOSSnapshotTestCase χρησιμοποιεί απόδοση UIKit σε CGImage. Αποτέλεσμα — ένα αρχείο PNG σταθερού μεγέθους.

Μέγεθος golden-αρχείων και διαχείριση αποθήκευσης

Golden-αρχεία — ένα στιγμιότυπο PNG μιας οθόνης (1080x1920) καταλαμβάνει 200-800 KB ανάλογα με την πολυπλοκότητα. Για ένα έργο με 500 golden-test, αυτό είναι ~100-400 MB στο αποθετήριο. Λύσεις: (1) αποθήκευση golden σε Git LFS. (2) Χρήση συμπίεσης PNG (pngcrush, oxipng). (3) Αποθήκευση golden σε ξεχωριστό χώρο αποθήκευσης (S3) και λήψη κατά την κατασκευή. Στο IT Sectr αποθηκεύουμε golden σε Git LFS με όριο 1 MB ανά αρχείο — αυτό είναι αρκετό για το 90% των δοκιμών.

Flaky golden test και η λύση τους

Flaky golden test — το κύριο πρόβλημα των golden-test. Διαφορετικές GPU, εκδόσεις γραμματοσειρών και anti-aliasing δίνουν μικρο-διαφορές στα pixel. Λύσεις: threshold (επιτρεπόμενο ποσοστό διαφορετικών pixel), fuzzy comparison (θολή σύγκριση) και εκτέλεση σε πανομοιότυπους CI agents (ίδια GPU, OS, έκδοση εξομοιωτή). Στο Paparazzi χρησιμοποιείται σύγκριση pixel-perfect, επομένως οι CI agents πρέπει να είναι πανομοιότυποι.

Golden Test vs Screenshot Test: ποια είναι η διαφορά;

Golden Test — είναι ένα είδος screenshot-testing με σταθερό πρότυπο. Ο όρος “golden” σημαίνει ότι το πρότυπο έχει εγκριθεί (γίνει αποδεκτό) από την ομάδα και αποθηκεύεται στο αποθετήριο. Κάθε αλλαγή της εικόνας απαιτεί συνειδητή απόφαση του προγραμματιστή: ενημέρωση του golden ή διόρθωση του κώδικα. Το Golden Test λειτουργεί σε επίπεδο μεμονωμένων στοιχείων (Composable, UIView) και δεν απαιτεί πραγματική συσκευή.

Screenshot Test — ευρύτερη έννοια. Το Screenshot-test μπορεί να καταγράψει ολόκληρη την οθόνη με πραγματικά δεδομένα, πλοήγηση, γραμμή κατάστασης συστήματος και κινούμενα σχέδια. Τα Screenshot-test συχνά εκτελούνται σε πραγματικές συσκευές ή εξομοιωτές μέσω UI Automator (Android) ή XCUITest (iOS). Τα Golden-test λειτουργούν σε περιβάλλον unit-test (JVM, XCTest) χωρίς εξομοιωτή και καταγράφουν μόνο ένα μεμονωμένο στοιχείο.

ΧαρακτηριστικόGolden TestScreenshot Test
ΕπίπεδοΣτοιχείο/Composable/ViewΟλόκληρη οθόνη
ΠεριβάλλονUnit-test (προσωρινή μνήμη εκτός οθόνης)Συσκευή/Εξομοιωτής
Ταχύτητα50-200 ms ανά δοκιμή2-30 δευτερόλεπτα ανά δοκιμή
Κινούμενα σχέδιαΔεν υποστηρίζονταιΥποστηρίζονται (με παύσεις)
CI χωρίς GPUΛειτουργεί (Layoutlib)Απαιτεί εξομοιωτή
Πολυπλοκότητα ρύθμισηςΧαμηλήΥψηλή (Εξομοιωτής/Device Farm)
FlakinessΜέτρια (διαφορετικές GPU)Υψηλή (εξομοιωτής, χρόνος)

Στρατηγική κάλυψης: golden vs screenshot

Golden vs Screenshot — golden-test για έλεγχο μεμονωμένων στοιχείων UI (κουμπί, κάρτα, διάλογος) σε κάθε commit. Screenshot-test — για έλεγχο E2E ολόκληρων οθονών πριν από την κυκλοφορία. Τα golden-test παρέχουν γρήγορη ανατροφοδότηση στον προγραμματιστή, τα screenshot-test — εμπιστοσύνη στην ακεραιότητα ολόκληρης της εφαρμογής. Στο IT Sectr χρησιμοποιούμε golden-test για Pull Request (3-5 λεπτά) και screenshot-test για nightly (30-60 λεπτά).

Paparazzi και Roborazzi: snapshot-testing στο Android

Paparazzi — βιβλιοθήκη από την Cash App (Square) που αποδίδει στοιχεία Android View και Jetpack Compose σε PNG χωρίς εξομοιωτή. Χρησιμοποιεί Layoutlib (τον ίδιο κινητήρα με το Android Studio Preview). Ρύθμιση: σύνδεση πρόσθετου Gradle, σύνταξη δοκιμής με @Test και @RunWith(PaparazziRule::class), κλήση paparazzi.snapshot(view). Το Paparazzi δεν υποστηρίζει κινούμενα σχέδια, βίντεο και Real Device — μόνο στατική απόδοση στοιχείων.

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

// Golden test για στοιχείο 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 — εναλλακτική λύση για το Paparazzi με υποστήριξη Compose, View και σύγκρισης εικόνων. Διαφορά: το Roborazzi λειτουργεί μέσω Robolectric και υποστηρίζει threshold (ποσοστό επιτρεπόμενης διαφοράς pixel). Αυτό μειώνει το flakiness με διαφορετικές GPU στο CI. Το Roborazzi μπορεί επίσης να δημιουργήσει κινούμενα σχέδια GIF αλλαγών (πριν/μετά/diff), που είναι βολικό για ανασκόπηση κώδικα. Μορφή golden-αρχείων: PNG + μεταδεδομένα JSON.

Ενημέρωση golden — μετά από σκόπιμη αλλαγή UI, ο προγραμματιστής διαγράφει τα παλιά golden-αρχεία και εκτελεί τις δοκιμές με τη σημαία record. Το Paparazzi δημιουργεί ξανά όλα τα golden-αρχεία. Στη συνέχεια, ο προγραμματιστής κάνει commit το νέο golden μαζί με την αλλαγή κώδικα. Στην ανασκόπηση κώδικα, ο κριτής βλέπει το diff των παλιών και νέων golden. Εάν οι αλλαγές εγκριθούν — το PR συγχωνεύεται. Εάν όχι — ο προγραμματιστής διορθώνει τον κώδικα και εκτελεί ξανά τις δοκιμές. Μην ενημερώνετε ποτέ το golden αυτόματα στο CI — μόνο τοπικά.

SwiftSnapshotTesting και iOSSnapshotTestCase στο iOS

SwiftSnapshotTesting — βιβλιοθήκη από την pointfree.co, δημιουργοί του Composable Architecture. Υποστηρίζει UIView, UIViewController, CALayer και SwiftUI View. Αρχή: assertSnapshot(matching: view, as: .image). Κατά την πρώτη εκτέλεση, το golden δημιουργείται αυτόματα. Στις επόμενες — συγκρίνεται. Εάν η διαφορά υπερβαίνει το επιτρεπόμενο όριο — η δοκιμή αποτυγχάνει. Το SwiftSnapshotTesting λειτουργεί μέσω UIGraphicsImageRenderer, το οποίο είναι συμβατό με 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 (πρώην FBSnapshotTestCase) — βιβλιοθήκη από την Uber για UIKit. Σε αντίθεση με το SwiftSnapshotTesting, το iOSSnapshotTestCase απαιτεί τον καθορισμό μεγέθους οθόνης και προσανατολισμού. Golden-αρχεία — PNG στο φάκελο ReferenceImages. Πλεονέκτημα: λειτουργεί με UIKit χωρίς SwiftUI και υποστηρίζει iOS 12+. Μειονέκτημα: δεν ενημερώνει αυτόματα το golden — πρέπει να εκτελεστεί με σημαία record. Το SwiftSnapshotTesting είναι πιο σύγχρονο και συνιστάται για νέα έργα.

Golden συγκεκριμένης συσκευής — τα golden-αρχεία διαφέρουν για διαφορετικά μεγέθη οθόνης και προσανατολισμούς. Τυπική προσέγγιση: ονομασία golden ως TestName@3x~iPhone14.png. Το SwiftSnapshotTesting προσθέτει αυτόματα το επίθημα συσκευής εάν δοθεί η παράμετρος .image(on: .iPhoneSe). Στο Android, το Paparazzi χρησιμοποιεί DeviceConfig για τη ρύθμιση μεγέθους. Αποθηκεύστε golden για κάθε υποστηριζόμενο παράγοντα μορφής συσκευής ξεχωριστά. Μην χρησιμοποιείτε ένα golden για διαφορετικά μεγέθη — αυτό θα οδηγήσει σε flaky δοκιμές.

Εργασία με golden-αρχεία στο CI και διαχείριση ενημερώσεων

CI pipeline — τα golden-test πρέπει να εκτελούνται σε κάθε Pull Request. Εάν η δοκιμή αποτύχει, το CI εμφανίζει την εικόνα diff ως τεχνούργημα κατασκευής. Ο προγραμματιστής εξετάζει το diff και λαμβάνει απόφαση. Σημαντικό: τα golden-αρχεία που δημιουργούνται στο CI δεν γίνονται ποτέ αυτόματα commit. Μόνο τοπική δημιουργία από τον προγραμματιστή μετά από σκόπιμη αλλαγή. Τα GitHub Actions και GitLab CI υποστηρίζουν τη μεταφόρτωση τεχνουργημάτων (png, html) για προβολή diff στο πρόγραμμα περιήγησης.

Μέγεθος αποθετηρίου — τα golden-αρχεία μεγαλώνουν γρήγορα. 500 δοκιμές = 100-400 MB PNG. Λύσεις: (1) Git LFS — κάθε golden αποθηκεύεται σε LFS, κλωνοποιείται μόνο κατά το checkout. (2) Αποθήκευση golden σε ξεχωριστό αποθετήριο και σύνδεση ως υπομονάδα. (3) S3 + προσωρινή αποθήκευση — golden στο S3, το CI κατεβάζει μόνο τροποποιημένα αρχεία βάσει checksum. Στο IT Sectr χρησιμοποιούμε Git LFS με track *.png filter=lfs diff=lfs merge=lfs text=false. Τοπικά, τα golden βρίσκονται στο src/test/goldens/.

Ανασκόπηση κώδικα golden — το συνηθισμένο git diff δεν δείχνει αλλαγές PNG. Λύσεις: (1) Το GitHub ανοίγει εικόνες PNG με κλικ. (2) Χρήση Review Apps, όπου το golden-diff είναι ορατό στο πρόγραμμα περιήγησης. (3) Δημιουργία αναφοράς HTML με στήλες πριν/μετά/diff. Το Paparazzi δημιουργεί αναφορά HTML με τρεις στήλες: actual, expected, diff. Η αναφορά επισυνάπτεται στα τεχνουργήματα CI. Οι κριτές βλέπουν την αναφορά χωρίς να κατεβάζουν αρχεία τοπικά.

Πότε να ενημερώνετε το golden — μόνο μετά από συνειδητή αλλαγή UI. Αλλαγή γραμματοσειράς, χρώματος, απόστασης, εικονιδίου — το golden πρέπει να ενημερωθεί. Προσθήκη νέου κουμπιού, αναδιάταξη στοιχείων — το golden πρέπει να ενημερωθεί. Διόρθωση σφάλματος που αλλάζει την εμφάνιση — το golden πρέπει να ενημερωθεί. Αναδιάρθρωση χωρίς αλλαγή UI — το golden δεν πρέπει να ενημερωθεί. Εάν το golden αλλάζει χωρίς αλλαγή κώδικα UI — αυτό είναι flaky test που προκαλείται από το περιβάλλον, αναζητήστε την αιτία στους CI agents ή στις εκδόσεις εξαρτήσεων.

Συχνές ερωτήσεις

Σε τι διαφέρει το Golden Test από το Screenshot Test;

Golden Test — snapshot-test σε επίπεδο στοιχείου σε περιβάλλον unit-test (γρήγορο, χωρίς εξομοιωτή). Screenshot Test — καταγραφή ολόκληρης της οθόνης σε συσκευή ή εξομοιωτή (αργό, αλλά ρεαλιστικό). Το golden λειτουργεί με προσωρινή μνήμη εκτός οθόνης, το screenshot — με πραγματική οθόνη. Το golden είναι κατάλληλο για CI σε κάθε commit, το screenshot — για nightly πριν από την κυκλοφορία.

Πώς να αντιμετωπίσουμε τα flaky golden test;

Κύριες αιτίες: (1) Διαφορετικές GPU στο CI — χρησιμοποιήστε πανομοιότυπους CI agents. (2) Διαφορετικές εκδόσεις γραμματοσειρών — καθορίστε την έκδοση OS. (3) Διαφορετικό anti-aliasing — ρυθμίστε το threshold (Roborazzi, iOSSnapshotTestCase). (4) Κινούμενα σχέδια — απενεργοποιήστε τα κινούμενα σχέδια στις δοκιμές. (5) Στοιχεία συστήματος (γραμμή κατάστασης) — χρησιμοποιήστε device config χωρίς πλαίσιο. Το Paparazzi δεν είναι επιρρεπές σε flakiness λόγω Layoutlib.

Μπορεί να χρησιμοποιηθεί το Golden Test με Jetpack Compose;

Ναι. Το Paparazzi έχει ενσωματωμένη υποστήριξη για Compose μέσω paparazzi.snapshot { }. Το Roborazzi υποστηρίζει επίσης Compose. Στο iOS, το SwiftSnapshotTesting λειτουργεί με SwiftUI μέσω UIHostingController. Τα στοιχεία Compose αποδίδονται μέσω Layoutlib, το SwiftUI — μέσω απόδοσης UIKit. Περιορισμός: τα κινούμενα σχέδια Compose και SwiftUI δεν υποστηρίζονται — το golden-test καταγράφει μόνο την αρχική κατάσταση.

Πώς να αποδεχτούμε αυτόματα τις αλλαγές golden;

Μην αυτοματοποιείτε ποτέ την αποδοχή golden στο CI. Μόνο τοπικά: ο προγραμματιστής διαγράφει τα παλιά golden-αρχεία από τον κατάλογο και εκτελεί τις δοκιμές με τη σημαία record (Paparazzi: record=true, SwiftSnapshotTesting: record=true). Τα golden-αρχεία δημιουργούνται ξανά. Ο προγραμματιστής ελέγχει κάθε golden για ορθότητα, κάνει commit τις αλλαγές μαζί με τον κώδικα. Η αυτόματη αποδοχή στο CI θα οδηγήσει σε παράβλεψη σφαλμάτων UI.

Επιβραδύνει το Golden Test την κατασκευή;

Τα golden-test είναι ταχύτερα από τις ενόργανες δοκιμές (UI Automator, XCUITest). Ένα golden-test εκτελείται σε 50-200 ms (Paparazzi: 100-150 ms σε ένα μέσο MacBook Pro). 500 golden-test = 25-100 δευτερόλεπτα. Συγκρίνετε με screenshot-test μέσω εξομοιωτή: 5-30 δευτερόλεπτα ανά δοκιμή. Τα golden-test δεν επιβραδύνουν την κατασκευή: 100 δοκιμές = ~15 δευτερόλεπτα, το οποίο είναι αποδεκτό για επαλήθευση pre-merge.

Σύνοψη

  • Golden Test — οπτική δοκιμή στοιχείων UI μέσω σύγκρισης με εικόνα προτύπου PNG
  • Διαδικασία — απόδοση στοιχείου σε προσωρινή μνήμη εκτός οθόνης, σύγκριση pixel προς pixel, diff σε ασυμφωνία
  • Android — Paparazzi (Compose/View, Layoutlib) και Roborazzi (Compose/View, threshold, Robolectric)
  • iOS — SwiftSnapshotTesting (pointfree) και iOSSnapshotTestCase από την Uber για UIKit και SwiftUI
  • CI Pipeline — golden-test σε κάθε PR, τεχνουργήματα diff, μόνο τοπική ενημέρωση golden
  • Git LFS — υποχρεωτικό για αποθήκευση αρχείων PNG (100-400 MB για 500 δοκιμές)
  • Flakiness — σχετίζεται με GPU, γραμματοσειρές και anti-aliasing· επιλύεται με threshold και πανομοιότυπους CI agents

Θα αναπτύξουμε μια εφαρμογή για κινητά έτοιμη για χρήση

Η IT Sectr δημιουργεί εφαρμογές iOS και Android για νεοφυείς επιχειρήσεις και επιχειρήσεις από το 2017. Θα σας συμβουλεύσουμε και θα προτείνουμε την καλύτερη λύση.

Συζήτηση έργου

Διαβάστε επίσης