Golden Test — มันคืออะไร การทดสอบ snapshot ทำงานอย่างไรและการนำไปใช้

ผู้แต่ง: IT Sectr เผยแพร่เมื่อ: 2026-04-10 เวลาอ่าน: 9 นาที

Golden Test (การทดสอบ snapshot, การทดสอบแบบจำลอง) — วิธีการทดสอบ UI แบบเห็นภาพ โดยการแสดงผลของคอมโพเนนต์ปัจจุบันถูกเปรียบเทียบกับภาพอ้างอิงที่บันทึกไว้ล่วงหน้า (ไฟล์ golden) หากการเปลี่ยนแปลงพิกเซลเกินเกณฑ์ที่กำหนดไว้ การทดสอบจะล้มเหลวและสร้างภาพ diff นักพัฒนาตรวจสอบ diff และยอมรับการเปลี่ยนแปลง (อัปเดต golden) หรือแก้ไขข้อผิดพลาด อ่านเพิ่มเติมใน บทความ Meta Engineering เกี่ยวกับ Paparazzi.

ประเด็นสำคัญ

  • Golden Test — เปรียบเทียบ UI ปัจจุบันกับภาพอ้างอิงเพื่อค้นหาการถดถอยทางสายตา
  • ภาพ diff — เมื่อ golden test ล้มเหลว จะสร้าง diff ที่เน้นพิกเซลที่เปลี่ยนแปลง
  • Android — Paparazzi และ Roborazzi สำหรับการทดสอบ screenshot ของคอมโพเนนต์ Compose และ View
  • iOS — SwiftSnapshotTesting (pointfree.co) และ iOSSnapshotTestCase โดย Uber สำหรับ SwiftUI และ UIKit
  • การผนวก CI — golden test ทำงานบน CI และล้มเหลวเมื่อมีการเปลี่ยนแปลง UI ที่ไม่คาดคิด

Golden Test คืออะไรและทำงานอย่างไร?

Golden Test — การตรวจสอบลักษณะทางสายตาของคอมโพเนนต์โดยอัตโนมัติผ่านการเปรียบเทียบแบบทีละพิกเซลกับแบบจำลอง กระบวนการ: (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, เวอร์ชันแบบอักษร และการป้องกันรอยหยักที่แตกต่างกันทำให้เกิดความแตกต่างเล็กน้อยในพิกเซล วิธีแก้ไข: threshold (เปอร์เซ็นต์ที่ยอมรับได้ของพิกเซลที่แตกต่างกัน), fuzzy comparison (การเปรียบเทียบแบบเลือนลาง) และการทำงานบน CI agents ที่เหมือนกัน (GPU, OS, เวอร์ชันโปรแกรมจำลองเดียวกัน) Paparazzi ใช้การเปรียบเทียบแบบ pixel-perfect ดังนั้น CI agents ต้องเหมือนกัน

Golden Test vs Screenshot Test: แตกต่างกันอย่างไร?

Golden Test — เป็นการทดสอบ screenshot ชนิดหนึ่งที่มีแบบจำลองคงที่ คำว่า "golden" หมายความว่าแบบจำลองได้รับการอนุมัติจากทีมและจัดเก็บไว้ในคลังโค้ด การเปลี่ยนแปลงภาพใด ๆ ต้องมีการตัดสินใจอย่างมีสติของนักพัฒนา: อัปเดต golden หรือแก้ไขโค้ด Golden Test ทำงานในระดับของคอมโพเนนต์แต่ละตัว (Composable, UIView) และไม่ต้องใช้อุปกรณ์จริง

Screenshot Test — เป็นแนวคิดที่กว้างกว่า การทดสอบ screenshot สามารถเก็บภาพทั้งหน้าจอด้วยข้อมูลจริง การนำทาง แถบสถานะระบบและแอนิเมชัน การทดสอบ screenshot มักทำงานบนอุปกรณ์จริงหรือโปรแกรมจำลองผ่าน UI Automator (Android) หรือ XCUITest (iOS) Golden test ทำงานในสภาพแวดล้อมการทดสอบหน่วย (JVM, XCTest) โดยไม่ต้องใช้โปรแกรมจำลองและเก็บภาพเฉพาะคอมโพเนนต์เดียว

ลักษณะGolden TestScreenshot Test
ระดับคอมโพเนนต์/Composable/Viewทั้งหน้าจอ
สภาพแวดล้อมการทดสอบหน่วย (off-screen buffer)อุปกรณ์/โปรแกรมจำลอง
ความเร็ว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 ตอนกลางคืน (30–60 นาที)

Paparazzi และ Roborazzi: การทดสอบ snapshot บน Android

Paparazzi — ไลบรารีจาก Cash App (Square) ที่แสดงผลคอมโพเนนต์ Android View และ Jetpack Compose เป็น PNG โดยไม่ต้องใช้โปรแกรมจำลอง ใช้ Layoutlib (เครื่องมือเดียวกับ Android Studio Preview) การตั้งค่า: เพิ่ม Gradle plugin เขียนการทดสอบด้วย @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 (เปอร์เซ็นต์ความแตกต่างของพิกเซลที่ยอมรับได้) ซึ่งช่วยลดความไม่เสถียรเมื่อใช้ GPU ต่างกันบน CI Roborazzi ยังสามารถสร้างแอนิเมชัน GIF ของการเปลี่ยนแปลง (ก่อน/หลัง/diff) ซึ่งสะดวกสำหรับการตรวจสอบโค้ด รูปแบบไฟล์: PNG + ข้อมูลเมตา JSON

การอัปเดต golden — หลังจากการเปลี่ยนแปลง UI โดยเจตนา นักพัฒนาลบไฟล์ golden เก่าและรันการทดสอบด้วยแฟล็ก record Paparazzi จะสร้างไฟล์ golden ใหม่ทั้งหมด จากนั้นนักพัฒนาจะ commit ไฟล์ golden ใหม่พร้อมกับการเปลี่ยนแปลงโค้ด ในการตรวจสอบโค้ด ผู้ตรวจสอบจะเห็น diff ของไฟล์ golden เก่าและใหม่ หากการเปลี่ยนแปลงได้รับการอนุมัติ — PR จะถูก merge หากไม่ — นักพัฒนาแก้ไขโค้ดและรันการทดสอบใหม่ ห้ามอัปเดตไฟล์ 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 แยกต่างหากสำหรับแต่ละ device form factor ที่รองรับ อย่าใช้ golden เดียวกันสำหรับขนาดที่แตกต่างกัน — จะนำไปสู่การทดสอบที่ไม่เสถียร

การทำงานกับไฟล์ 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 จะถูก clone เฉพาะเมื่อ 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 ที่ diff ของ golden สามารถดูได้ในเบราว์เซอร์ (3) สร้างรายงาน HTML ที่มีคอลัมน์ ก่อน/หลัง/diff Paparazzi สร้างรายงาน HTML ที่มีสามคอลัมน์: actual, expected, diff รายงานจะถูกแนบไปกับ CI artifacts ผู้ตรวจสอบดูรายงานโดยไม่ต้องดาวน์โหลดไฟล์ในเครื่อง

เมื่อใดควรอัปเดต golden — หลังจากการเปลี่ยนแปลง UI อย่างมีสติเท่านั้น การเปลี่ยนแบบอักษร สี ระยะห่าง ไอคอน — golden ต้องได้รับการอัปเดต การเพิ่มปุ่มใหม่ การจัดเรียงองค์ประกอบใหม่ — golden ต้องได้รับการอัปเดต การแก้ไขข้อบกพร่องที่เปลี่ยนลักษณะทางสายตา — golden ต้องได้รับการอัปเดต การปรับโครงสร้างโค้ดโดยไม่มีการเปลี่ยนแปลง UI — golden ไม่ควรเปลี่ยนแปลง หาก golden เปลี่ยนแปลงโดยไม่มีการเปลี่ยนแปลงโค้ด UI — นี่คือ flaky test ที่เกิดจากสภาพแวดล้อม ให้ค้นหาสาเหตุใน CI agents หรือเวอร์ชันของ dependencies

คำถามที่พบบ่อย

Golden Test แตกต่างจาก Screenshot Test อย่างไร?

Golden Test — การทดสอบ snapshot ในระดับคอมโพเนนต์ในสภาพแวดล้อมการทดสอบหน่วย (เร็ว, ไม่ต้องใช้โปรแกรมจำลอง) Screenshot Test — การเก็บภาพทั้งหน้าจอบนอุปกรณ์หรือโปรแกรมจำลอง (ช้ากว่า แต่สมจริง) Golden ทำงานกับ off-screen buffer, screenshot ทำงานกับหน้าจอจริง Golden เหมาะสำหรับ CI ในทุก commit, screenshot สำหรับการรันตอนกลางคืนก่อนเผยแพร่

จัดการกับ golden test ที่ไม่เสถียรอย่างไร?

สาเหตุหลัก: (1) GPU ต่างกันบน CI — ใช้ CI agents ที่เหมือนกัน (2) เวอร์ชันแบบอักษรที่แตกต่างกัน — กำหนดเวอร์ชัน OS (3) การป้องกันรอยหยักที่แตกต่างกัน — ตั้งค่า threshold (Roborazzi, iOSSnapshotTestCase) (4) แอนิเมชัน — ปิดแอนิเมชันในการทดสอบ (5) องค์ประกอบระบบ (แถบสถานะ) — ใช้การกำหนดค่าอุปกรณ์ไร้ขอบ Paparazzi ไม่มีปัญหา flakiness เนื่องจาก Layoutlib

สามารถใช้ Golden Test กับ Jetpack Compose ได้หรือไม่?

ได้ Paparazzi มีการรองรับ Compose ในตัวผ่าน paparazzi.snapshot { } Roborazzi ก็รองรับ Compose เช่นกัน บน iOS SwiftSnapshotTesting ทำงานกับ SwiftUI ผ่าน UIHostingController คอมโพเนนต์ Compose ถูกแสดงผลผ่าน Layoutlib, SwiftUI ผ่าน UIKit rendering ข้อจำกัด: ไม่รองรับแอนิเมชัน Compose และ SwiftUI — golden test เก็บภาพเฉพาะสถานะเริ่มต้น

จะยอมรับการเปลี่ยนแปลง golden โดยอัตโนมัติอย่างไร?

ห้ามทำให้การยอมรับ golden เป็นอัตโนมัติบน CI เฉพาะในเครื่องเท่านั้น: นักพัฒนาลบไฟล์ golden เก่าจากไดเรกทอรีและรันการทดสอบด้วยแฟล็ก record (Paparazzi: record=true, SwiftSnapshotTesting: record=true) ไฟล์ golden จะถูกสร้างใหม่ นักพัฒนาตรวจสอบแต่ละ golden ว่าถูกต้องหรือไม่ และ commit การเปลี่ยนแปลงพร้อมกับโค้ด การยอมรับโดยอัตโนมัติบน CI จะนำไปสู่การพลาดข้อผิดพลาดใน UI

Golden Test ทำให้การสร้างช้าลงหรือไม่?

Golden test เร็วกว่าการทดสอบแบบ instrumented (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 วินาที ซึ่งยอมรับได้สำหรับการตรวจสอบก่อน merge

สรุป

  • Golden Test — การทดสอบภาพของคอมโพเนนต์ UI โดยการเปรียบเทียบกับภาพ PNG อ้างอิง
  • กระบวนการ — แสดงผลคอมโพเนนต์ใน off-screen buffer, เปรียบเทียบทีละพิกเซล, diff เมื่อไม่ตรงกัน
  • Android — Paparazzi (Compose/View, Layoutlib) และ Roborazzi (Compose/View, threshold, Robolectric)
  • iOS — SwiftSnapshotTesting (pointfree) และ iOSSnapshotTestCase โดย Uber สำหรับ UIKit และ SwiftUI
  • CI Pipeline — golden test ในทุก PR, diff artifacts, เฉพาะการอัปเดต golden ในเครื่อง
  • Git LFS — บังคับสำหรับจัดเก็บไฟล์ PNG (100–400 MB สำหรับ 500 การทดสอบ)
  • ความไม่เสถียร — เกี่ยวข้องกับ GPU, แบบอักษร และการป้องกันรอยหยัก; แก้ไขด้วย threshold และ CI agents ที่เหมือนกัน

เราจะพัฒนาแอปพลิเคชันบนมือถือแบบครบวงจร

IT Sectr สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ

ปรึกษาโครงการ

อ่านเพิ่มเติม