Golden Test — nó là gì, kiểm thử snapshot hoạt động thế nào và ứng dụng

Tác giả: IT Sectr Đã đăng: 2026-04-10 Thời gian đọc: 9 phút

Golden Test (kiểm thử snapshot, kiểm thử tham chiếu) — phương pháp kiểm thử trực quan UI, trong đó kết xuất hiện tại của thành phần được so sánh với hình ảnh tham chiếu được lưu trước (tệp golden). Nếu thay đổi pixel vượt quá ngưỡng đã đặt, kiểm thử thất bại và tạo hình ảnh diff. Nhà phát triển xem xét diff và chấp nhận thay đổi (cập nhật golden) hoặc sửa lỗi. Đọc thêm trong bài viết của Meta Engineering về Paparazzi.

Những điểm chính

  • Golden Test — so sánh UI hiện tại với hình ảnh tham chiếu để phát hiện hồi quy trực quan
  • Hình ảnh diff — khi golden test thất bại, nó tạo diff làm nổi bật các pixel đã thay đổi
  • Android — Paparazzi và Roborazzi cho kiểm thử screenshot các thành phần Compose và View
  • iOS — SwiftSnapshotTesting (pointfree.co) và iOSSnapshotTestCase của Uber cho SwiftUI và UIKit
  • Tích hợp CI — golden test chạy trên CI và thất bại khi có thay đổi UI không mong đợi

Golden Test là gì và nó hoạt động thế nào?

Golden Test là kiểm tra tự động giao diện trực quan của một thành phần bằng cách so sánh từng pixel với tham chiếu. Quy trình: (1) nhà phát triển hoặc người kiểm thử tạo ảnh chụp đầu tiên của thành phần — đây là “golden” (tham chiếu). (2) Tệp golden được lưu trong kho lưu trữ bên cạnh kiểm thử. (3) Trong các lần chạy tiếp theo, kiểm thử kết xuất lại thành phần và so sánh với golden đã lưu. (4) Nếu ảnh khớp — kiểm thử đật. Nếu khác — kiểm thử thất bại với diff. Quyết định: hoặc thay đổi được mong đợi (cập nhật golden) hoặc đó là lỗi.

Cách golden được tạo — thư viện kết xuất thành phần vào bộ đệm ngoài màn hình (Android: Canvas, iOS: UIGraphicsImageRenderer) mà không cần màn hình thật. Điều này có nghĩa là golden test hoạt động trên CI mà không cần trình giả lập màn hình (màn hình ảo), tăng tốc độ thực thi. Paparazzi trên Android sử dụng Layoutlib từ Android Studio — cùng công cụ mà Layout Editor sử dụng. iOSSnapshotTestCase sử dụng kết xuất UIKit trong CGImage. Kết quả là tệp PNG có kích thước cố định.

Kích thước tệp golden và quản lý lưu trữ

Tệp golden — ảnh chụp PNG của một màn hình (1080x1920) chiếm 200–800 KB tùy theo độ phức tạp. Đối với dự án có 500 golden test, đó là ~100–400 MB trong kho lưu trữ. Giải pháp: (1) lưu golden trong Git LFS. (2) Sử dụng nén PNG (pngcrush, oxipng). (3) Lưu golden trong bộ lưu trữ riêng (S3) và tải xuống khi xây dựng. Tại IT Sectr, chúng tôi lưu golden trong Git LFS với ngưỡng 1 MB trên mỗi tệp — đủ cho 90% kiểm thử.

Kiểm thử golden không ổn định (flaky) và giải pháp

Kiểm thử golden không ổn định — vấn đề chính của golden test. Các GPU, phiên bản phông chữ và khử răng cưa khác nhau tạo ra sự khác biệt vi mô trong pixel. Giải pháp: ngưỡng (tỷ lệ phần trăm pixel khác nhau cho phép), so sánh mờ (fuzzy), và chạy trên các tác nhân CI giống hệt nhau (cùng GPU, OS, phiên bản trình giả lập). Paparazzi sử dụng so sánh pixel-perfect, vì vậy các tác nhân CI phải giống hệt nhau.

Golden Test vs Screenshot Test: khác biệt là gì?

Golden Test là một loại kiểm thử screenshot với tham chiếu cố định. Thuật ngữ “golden” có nghĩa là tham chiếu đã được nhóm phê duyệt và lưu trong kho lưu trữ. Bất kỳ thay đổi hình ảnh nào cũng yêu cầu nhà phát triển đưa ra quyết định có ý thức: cập nhật golden hoặc sửa mã. Golden Test hoạt động ở cấp độ thành phần riêng lẻ (Composable, UIView) và không yêu cầu thiết bị thật.

Screenshot Test là một khái niệm rộng hơn. Kiểm thử screenshot có thể chụp toàn bộ màn hình với dữ liệu thật, điều hướng, thanh trạng thái hệ thống và hoạt ảnh. Kiểm thử screenshot thường được chạy trên thiết bị thật hoặc trình giả lập qua UI Automator (Android) hoặc XCUITest (iOS). Golden test chạy trong môi trường kiểm thử đơn vị (JVM, XCTest) mà không cần trình giả lập và chỉ chụp một thành phần duy nhất.

Đặc tínhGolden TestScreenshot Test
Cấp độThành phần/Composable/ViewToàn bộ màn hình
Môi trườngKiểm thử đơn vị (bộ đệm ngoài màn hình)Thiết bị/Trình giả lập
Tốc độ50–200 ms mỗi kiểm thử2–30 giây mỗi kiểm thử
Hoạt ảnhKhông được hỗ trợĐược hỗ trợ (có tạm dừng)
CI không có GPUHoạt động (Layoutlib)Yêu cầu trình giả lập
Độ phức tạp thiết lậpThấpCao (Trình giả lập/Device Farm)
Không ổn địnhTrung bình (GPU khác nhau)Cao (trình giả lập, thời gian)

Chiến lược bao phủ: golden vs screenshot

Golden vs Screenshot — golden test để kiểm tra các thành phần UI riêng lẻ (nút, thẻ, hộp thoại) ở mỗi commit. Screenshot test để kiểm tra E2E toàn bộ màn hình trước khi phát hành. Golden test cung cấp phản hồi nhanh cho nhà phát triển, screenshot test mang lại sự tự tin về tính toàn vẹn của toàn bộ ứng dụng. Tại IT Sectr, chúng tôi sử dụng golden test cho Pull Request (3–5 phút) và screenshot test hàng đêm (30–60 phút).

Paparazzi và Roborazzi: kiểm thử snapshot trên Android

Paparazzi — thư viện từ Cash App (Square) kết xuất các thành phần Android View và Jetpack Compose thành PNG mà không cần trình giả lập. Nó sử dụng Layoutlib (cùng công cụ mà Android Studio Preview sử dụng). Thiết lập: thêm plugin Gradle, viết kiểm thử với @Test và @RunWith(PaparazziRule::class), gọi paparazzi.snapshot(view). Paparazzi không hỗ trợ hoạt ảnh, video hay Real Device — chỉ kết xuất thành phần tĩnh.

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

// Golden test cho thành phần 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 — một thay thế cho Paparazzi với hỗ trợ Compose, View và so sánh hình ảnh. Khác biệt: Roborazzi hoạt động qua Robolectric và hỗ trợ ngưỡng (tỷ lệ phần trăm khác biệt pixel cho phép). Điều này giảm sự không ổn định với các GPU khác nhau trên CI. Roborazzi cũng có thể tạo hoạt ảnh GIF của các thay đổi (trước/sau/diff), thuận tiện cho việc xem xét mã. Định dạng tệp: PNG + siêu dữ liệu JSON.

Cập nhật golden — sau khi thay đổi UI có chủ đích, nhà phát triển xóa các tệp golden cũ và chạy kiểm thử với cờ record. Paparazzi tạo lại tất cả các tệp golden. Sau đó, nhà phát triển commit các tệp golden mới cùng với thay đổi mã. Trong quá trình xem xét mã, người xem xét thấy diff của các tệp golden cũ và mới. Nếu thay đổi được phê duyệt — PR được hợp nhất. Nếu không — nhà phát triển sửa mã và chạy lại kiểm thử. Không bao giờ cập nhật tệp golden tự động trên CI — chỉ cục bộ.

SwiftSnapshotTesting và iOSSnapshotTestCase trên iOS

SwiftSnapshotTesting — thư viện từ pointfree.co, những người tạo ra Composable Architecture. Hỗ trợ UIView, UIViewController, CALayer và SwiftUI View. Nguyên tắc: assertSnapshot(matching: view, as: .image). Ở lần chạy đầu tiên, golden được tạo tự động. Ở các lần chạy tiếp theo, nó được so sánh. Nếu sự khác biệt vượt quá ngưỡng cho phép, kiểm thử thất bại. SwiftSnapshotTesting hoạt động qua UIGraphicsImageRenderer, tương thích với 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 (trước đây là FBSnapshotTestCase) — thư viện của Uber cho UIKit. Không giống SwiftSnapshotTesting, iOSSnapshotTestCase yêu cầu chỉ định kích thước và hướng màn hình. Các tệp golden là PNG trong thư mục ReferenceImages. Lợi thế: hoạt động với UIKit mà không cần SwiftUI và hỗ trợ iOS 12+. Nhược điểm: không tự động cập nhật golden — phải chạy với cờ record. SwiftSnapshotTesting hiện đại hơn và được khuyến nghị cho các dự án mới.

Golden theo thiết bị cụ thể — các tệp golden khác nhau cho các kích thước màn hình và hướng khác nhau. Cách tiếp cận tiêu chuẩn: đặt tên tệp golden là TestName@3x~iPhone14.png. SwiftSnapshotTesting tự động thêm hậu tố thiết bị nếu tham số .image(on: .iPhoneSe) được chỉ định. Trên Android, Paparazzi sử dụng DeviceConfig để đặt kích thước. Lưu trữ golden riêng cho từng hệ số hình dạng thiết bị được hỗ trợ. Không sử dụng một golden cho các kích thước khác nhau — điều này sẽ dẫn đến các kiểm thử không ổn định.

Làm việc với tệp golden trong CI và quản lý cập nhật

CI pipeline — golden test nên chạy trên mọi Pull Request. Nếu kiểm thử thất bại, CI hiển thị hình ảnh diff như một tài sản xây dựng. Nhà phát triển xem xét diff và đưa ra quyết định. Quan trọng: các tệp golden được tạo trên CI không bao giờ được commit tự động. Chỉ tạo cục bộ bởi nhà phát triển sau khi thay đổi có chủ đích. GitHub Actions và GitLab CI hỗ trợ tải lên tài sản (png, html) để xem diff trong trình duyệt.

Kích thước kho lưu trữ — các tệp golden tăng nhanh. 500 kiểm thử = 100–400 MB PNG. Giải pháp: (1) Git LFS — mỗi golden được lưu trong LFS, chỉ được sao chép khi checkout. (2) Lưu golden trong kho lưu trữ riêng và đưa vào như mô-đun con. (3) S3 + bộ nhớ đệm — golden trên S3, CI chỉ tải xuống các tệp đã thay đổi theo checksum. Tại IT Sectr, chúng tôi sử dụng Git LFS với track *.png filter=lfs diff=lfs merge=lfs text=false. Cục bộ, các tệp golden nằm trong src/test/goldens/.

Xem xét mã golden — git diff thông thường không hiển thị thay đổi PNG. Giải pháp: (1) GitHub mở hình ảnh PNG khi nhấp chuột. (2) Sử dụng Review Apps nơi golden diff hiển thị trong trình duyệt. (3) Tạo báo cáo HTML với các cột trước/sau/diff. Paparazzi tạo báo cáo HTML với ba cột: thực tế, dự kiến, diff. Báo cáo được đính kèm với tài sản CI. Người xem xét xem báo cáo mà không cần tải tệp xuống cục bộ.

Khi nào cập nhật golden — chỉ sau khi thay đổi UI có ý thức. Thay đổi phông chữ, màu sắc, khoảng đệm, biểu tượng — golden phải được cập nhật. Thêm nút mới, sắp xếp lại các phần tử — golden phải được cập nhật. Sửa lỗi làm thay đổi giao diện trực quan — golden phải được cập nhật. Tái cấu trúc mã không thay đổi UI — golden không nên thay đổi. Nếu golden thay đổi mà không có thay đổi mã UI — đó là kiểm thử không ổn định do môi trường, hãy tìm nguyên nhân trong các tác nhân CI hoặc phiên bản phụ thuộc.

Câu hỏi thường gặp

Golden Test khác Screenshot Test như thế nào?

Golden Test — kiểm thử snapshot ở cấp thành phần trong môi trường kiểm thử đơn vị (nhanh, không cần trình giả lập). Screenshot Test — chụp toàn bộ màn hình trên thiết bị hoặc trình giả lập (chậm hơn nhưng thực tế). Golden hoạt động với bộ đệm ngoài màn hình, screenshot hoạt động với màn hình thật. Golden phù hợp cho CI ở mỗi commit, screenshot cho các lần chạy hàng đêm trước khi phát hành.

Làm thế nào đối phó với golden test không ổn định?

Nguyên nhân chính: (1) GPU khác nhau trên CI — sử dụng các tác nhân CI giống hệt nhau. (2) Phiên bản phông chữ khác nhau — cố định phiên bản OS. (3) Khử răng cưa khác nhau — cấu hình ngưỡng (Roborazzi, iOSSnapshotTestCase). (4) Hoạt ảnh — tắt hoạt ảnh trong kiểm thử. (5) Yếu tố hệ thống (thanh trạng thái) — sử dụng cấu hình thiết bị không viền. Paparazzi không dễ bị không ổn định nhờ Layoutlib.

Có thể sử dụng Golden Test với Jetpack Compose không?

Có. Paparazzi có hỗ trợ Compose tích hợp qua paparazzi.snapshot { }. Roborazzi cũng hỗ trợ Compose. Trên iOS, SwiftSnapshotTesting hoạt động với SwiftUI qua UIHostingController. Các thành phần Compose được kết xuất qua Layoutlib, SwiftUI qua kết xuất UIKit. Hạn chế: hoạt ảnh Compose và SwiftUI không được hỗ trợ — golden test chỉ chụp trạng thái ban đầu.

Làm thế nào để tự động chấp nhận thay đổi golden?

Không bao giờ tự động hóa việc chấp nhận golden trên CI. Chỉ cục bộ: nhà phát triển xóa các tệp golden cũ khỏi thư mục và chạy kiểm thử với cờ record (Paparazzi: record=true, SwiftSnapshotTesting: record=true). Các tệp golden được tạo lại. Nhà phát triển kiểm tra từng golden xem có chính xác không, commit thay đổi cùng với mã. Tự động chấp nhận trên CI sẽ dẫn đến bỏ sót lỗi UI.

Golden Test có làm chậm quá trình xây dựng không?

Golden test nhanh hơn kiểm thử công cụ (UI Automator, XCUITest). Một golden test thực hiện trong 50–200 ms (Paparazzi: 100–150 ms trên MacBook Pro trung bình). 500 golden test = 25–100 giây. So sánh với kiểm thử screenshot qua trình giả lập: 5–30 giây mỗi kiểm thử. Golden test không làm chậm quá trình xây dựng: 100 kiểm thử = ~15 giây, chấp nhận được cho việc kiểm tra trước khi hợp nhất.

Tóm tắt

  • Golden Test — kiểm thử trực quan các thành phần UI bằng cách so sánh với hình ảnh PNG tham chiếu
  • Quy trình — kết xuất thành phần trong bộ đệm ngoài màn hình, so sánh từng pixel, diff khi không khớp
  • Android — Paparazzi (Compose/View, Layoutlib) và Roborazzi (Compose/View, ngưỡng, Robolectric)
  • iOS — SwiftSnapshotTesting (pointfree) và iOSSnapshotTestCase của Uber cho UIKit và SwiftUI
  • CI Pipeline — golden test trên mọi PR, tài sản diff, chỉ cập nhật golden cục bộ
  • Git LFS — bắt buộc để lưu trữ tệp PNG (100–400 MB cho 500 kiểm thử)
  • Không ổn định — liên quan đến GPU, phông chữ và khử răng cưa; được giải quyết bằng ngưỡng và tác nhân CI giống hệt nhau

Chúng tôi sẽ phát triển ứng dụng di động chìa khóa trao tay

IT Sectr tạo các ứng dụng iOS và Android cho các công ty khởi nghiệp và doanh nghiệp từ năm 2017. Chúng tôi sẽ tư vấn và đề xuất giải pháp tốt nhất cho bạn.

Thảo luận dự án

Đọc thêm