Screenshot Test là việc kiểm tra tự động giao diện người dùng bằng cách chụp và so sánh ảnh chụp màn hình của ứng dụng với hình ảnh tham chiếu. Không giống như golden test, screenshot test được thực hiện trên thiết bị thật hoặc trình giả lập, chụp toàn bộ màn hình với điều hướng, các yếu tố hệ thống và hoạt ảnh, và sử dụng UI Automator (Android) hoặc XCUITest (iOS) để tương tác với ứng dụng. Chi tiết trong tài liệu Android UI Automator.
Những điểm chính
Screenshot Test là kiểm thử giao diện người dùng từ đầu đến cuối, nơi bài kiểm thử mở màn hình ứng dụng, thực hiện các thao tác (chạm, nhập văn bản, cuộn) và chụp ảnh màn hình của trạng thái kết quả. Ảnh chụp màn hình được so sánh với đường cơ sở (baseline) được lưu trữ trong kho lưu trữ. Nếu ảnh chụp khác nhau — bài kiểm thử thất bại. Screenshot test phát hiện các hồi quy trực quan mà kiểm thử đơn vị không thể thấy: lề không chính xác, phần tử chồng lấn, màu sắc sai.
Tại sao cần screenshot test nếu đã có golden test? — golden test kiểm tra các thành phần riêng lẻ: một nút, một thẻ, một văn bản. Screenshot test kiểm tra toàn bộ màn hình trong môi trường gần với sản xuất nhất có thể: điều hướng thực tế, dữ liệu thực tế (hoặc mô phỏng thực tế tối đa), phông chữ hệ thống thực tế, thanh trạng thái thực tế. Chỉ có screenshot test mới cho thấy một nút bị chồng lấn với phần tử khác trên thiết bị thật.
Giá trị kinh doanh — theo Google (2023), lỗi trực quan chiếm 15-25% tổng số lỗi ứng dụng di động. Screenshot test tự động hóa việc kiểm tra chất lượng trực quan trước đây được thực hiện thủ công bởi các kỹ sư QA. Một screenshot test thay thế 5-10 phút kiểm thử thủ công một màn hình. Đối với ứng dụng có 50 màn hình, tiết kiệm: 4-8 giờ công mỗi lần chạy kiểm thử hồi quy. Screenshot test hoàn vốn sau 2-3 chu kỳ phát hành.
Golden test nhanh hơn và đơn giản hơn: kết xuất một thành phần trong bộ đệm ngoài màn hình mất mili giây, không cần thiết bị và ổn định trên CI. Screenshot test thực tế hơn: chúng chụp màn hình thật với các yếu tố hệ thống, hỗ trợ hoạt ảnh và điều hướng, và hoạt động trên thiết bị thật. Sự lựa chọn phụ thuộc vào mục tiêu: phản hồi nhanh cho nhà phát triển (golden) hoặc tính thực tế tối đa trước khi phát hành (screenshot).
| Đặc tính | Screenshot Test | Golden Test |
|---|---|---|
| Tốc độ | 2-30 giây | 50-200 ms |
| Tính thực tế | Tối đa (thiết bị thật) | Hạn chế (ngoài màn hình) |
| Cần thiết bị | Có (trình giả lập/vật lý) | Không (JVM, XCTest) |
| Hoạt ảnh | Hỗ trợ | Không hỗ trợ |
| Điều hướng | Kịch bản nhiều bước | Một thành phần |
| Tính không ổn định | Cao (mạng, thời gian) | Trung bình (GPU, phông chữ) |
| Song song | Device Farm (Firebase, AWS) | Đa luồng JVM/XCTest |
Golden + Screenshot — sử dụng golden test cho mỗi thành phần UI trong thư viện thành phần (Design System). 80% hồi quy trực quan được phát hiện ở cấp độ thành phần. Screenshot test — cho các luồng người dùng quan trọng: onboarding, đăng nhập, luồng thanh toán, giỏ hàng. 20% hồi quy liên quan đến tích hợp thành phần trên màn hình thật chỉ được phát hiện bởi screenshot test. Tại IT Sectr, chúng tôi sử dụng tỷ lệ 80/20: 400 golden + 100 screenshot.
Khi nào không cần screenshot test — nếu màn hình bao gồm nội dung tĩnh không có tương tác, golden test thành phần cung cấp cùng mức độ xác minh với chi phí thấp hơn. Nếu màn hình thay đổi động (nguồn cấp dữ liệu, trò chuyện), screenshot test yêu cầu thiết lập dữ liệu phức tạp và thời gian chờ. Trong những trường hợp này, sử dụng screenshot cho trạng thái cơ sở (danh sách trống, đang tải) và golden cho các thẻ riêng lẻ trong danh sách.
UI Automator là framework Android để kiểm thử UI xuyên ứng dụng. Nó cho phép chụp ảnh màn hình qua UiDevice.takeScreenshot(). Không giống Espresso (hoạt động trong một ứng dụng duy nhất), UI Automator có thể tương tác với hộp thoại hệ thống (quyền, thông báo) và các ứng dụng khác. Một screenshot test trên UI Automator: mở ứng dụng, chờ tải, chụp ảnh màn hình, so sánh với đường cơ sở.
class LoginScreenScreenshotTest {
@get:Rule
val rule = ComposeTestRule.createAndroidComposeRule<MainActivity>()
@Test
fun login_screen_default() {
val device = UiDevice.getInstance(
InstrumentationRegistry.getInstrumentation()
)
// Chờ màn hình tải xong
IdlingRegistry.getInstance().waitForIdle()
// Chụp màn hình
val screenshot = device.takeScreenshot()
val golden = loadGolden("login_default.png")
// So sánh với mẫu chuẩn
val diff = ImageComparator.compare(screenshot, golden)
assertTrue(diff.similarity > 0.98)
}
}
Firebase Test Lab là dịch vụ Google Cloud để chạy các kiểm thử công cụ trên hàng trăm thiết bị thật song song. Các screenshot test trên Firebase Test Lab chụp ảnh màn hình trên các thiết bị khác nhau (Pixel 7, Galaxy S24, Xiaomi 14) và so sánh với đường cơ sở. Ưu điểm: một kiểm thử kiểm tra UI trên 20 thiết bị trong 10-15 phút. Nhược điểm: chi phí ($1-5 mỗi kiểm thử trên 20 thiết bị). Firebase Test Lab tích hợp với CI qua gcloud CLI hoặc plugin Gradle.
Shot là thư viện cho screenshot testing trên Android giúp đơn giản hóa việc tạo và so sánh ảnh chụp màn hình. Shot hoạt động trên nền Espresso và UI Automator, thêm quản lý golden (tạo, cập nhật, xóa), so sánh với ngưỡng (pixel hoặc phần trăm) và tạo báo cáo HTML. Shot phù hợp với các dự án muốn nhanh chóng triển khai screenshot testing mà không cần viết cơ sở hạ tầng so sánh hình ảnh riêng.
XCUITest là framework của Apple để kiểm thử UI các ứng dụng iOS, iPadOS và tvOS. Các screenshot test trên XCUITest sử dụng XCUIScreen.main.screenshot() để chụp màn hình và XCAttachment để lưu ảnh chụp. XCUITest mô phỏng các thao tác người dùng: chạm, vuốt, typeText, và chụp ảnh sau mỗi bước. Trong Xcode 16+, hỗ trợ tích hợp sẵn để so sánh ảnh chụp với đường cơ sở qua XCTAttachment đã được thêm vào.
final class LoginScreenScreenshotTests: XCTestCase {
var app: XCUIApplication!
override func setUp() {
super.setUp()
app = XCUIApplication()
app.launch()
}
func test_login_initial_state() {
let loginButton = app.buttons["login_button"]
XCTAssertTrue(loginButton.exists)
// Chụp màn hình
let screenshot = app.screenshot()
let attachment = XCTAttachment(screenshot: screenshot)
attachment.name = "Login-Screen-Initial"
attachment.lifetime = .keepAlways
add(attachment)
// So sánh với mẫu chuẩn (cần XCTAttachment + golden)
assertScreenshot(
screenshot: screenshot,
goldenName: "login_initial_state"
)
}
}
Xcode Cloud là CI đám mây của Apple để xây dựng và kiểm thử các ứng dụng iOS. Xcode Cloud hỗ trợ chạy các kiểm thử XCUITest trên trình mô phỏng. Các screenshot test có thể được chạy trên nhiều trình mô phỏng song song (iPhone 15, iPhone 15 Pro Max, iPad Pro). Kết quả: XCResult Bundle với tệp đính kèm. Xcode Cloud không được tích hợp sẵn trong GitHub/GitLab — sử dụng Xcode Cloud Webhooks để tích hợp. Thay thế: GitHub Actions với macos-14 và xcodebuild.
Các framework so sánh — iOSSnapshotTestCase (Uber) cũng hoạt động cho screenshot test nếu chạy trên trình mô phỏng. SwiftSnapshotTesting (pointfree) thiên về golden test thành phần hơn. Đối với screenshot test trên iOS, sử dụng công cụ XCUITest tích hợp sẵn + XCTAttachment + ImageComparator tùy chỉnh (Pixelmator hoặc AImage). Trên CI sử dụng trình mô phỏng — trên thiết bị thật, screenshot test chỉ hoạt động qua Device Farm (AWS Device Farm).
Quản lý đường cơ sở — các ảnh chụp màn hình đường cơ sở được lưu trữ trong kho lưu trữ (Git LFS) hoặc trong S3. Mỗi ảnh chụp màn hình được đặt tên theo mẫu: {testName}_{device}_{orientation}_{locale}.png. Ví dụ: loginScreenPixel7PortraitRu.png. Khi thêm thiết bị hoặc ngôn ngữ mới, một đường cơ sở mới được tạo. Khi thay đổi UI, các đường cơ sở cũ được thay thế bằng các đường cơ sở mới sau khi xem xét mã. Đường cơ sở là một phần của cơ sở mã, giống như mã nguồn kiểm thử.
Pipeline CI — (1) Xây dựng ứng dụng. (2) Chạy screenshot test trên trình giả lập/trình mô phỏng. (3) So sánh ảnh chụp với đường cơ sở. (4) Nếu không khớp — tạo ảnh diff. (5) Tải lên các tệp diff (actual, expected, diff — ba tệp). (6) Xuất bản báo cáo HTML với bảng kết quả. (7) Nếu vượt quá ngưỡng — kiểm thử thất bại. (8) Người xem xét kiểm tra các tệp diff và đưa ra quyết định: phê duyệt (cập nhật đường cơ sở) hoặc từ chối (sửa mã).
Ngưỡng và dung sai — so sánh tuyệt đối từng pixel quá nghiêm ngặt. Sử dụng SSIM (Chỉ số Tương đồng Cấu trúc) hoặc MSE (Sai số Bình phương Trung bình). SSIM 0.98 = 98% tương đồng cấu trúc — một ngưỡng tốt. Các màn hình khác nhau có thể yêu cầu ngưỡng khác nhau: chủ đề tối (nhiều màu đen hơn — độ chính xác cao hơn), gradient (nhiều nhiễu hơn — độ chính xác thấp hơn). Cấu hình ngưỡng theo từng kiểm thử qua tham số: @ScreenshotTest(threshold = 0.99).
Device Farm vs Trình mô phỏng — kiểm thử trên thiết bị thật (Firebase Test Lab, AWS Device Farm) cung cấp tính thực tế tối đa nhưng chậm và tốn phí. Kiểm thử trên trình mô phỏng/trình giả lập nhanh và miễn phí nhưng không hiển thị các đặc điểm của thiết bị thật (GPU khác nhau, tái tạo màu sắc màn hình, mật độ pixel). Chiến lược: trình mô phỏng cho kiểm tra trước khi merge (5 phút), Device Farm cho chạy hàng đêm (30 phút, 20 thiết bị). Tại IT Sectr, chúng tôi sử dụng Firebase Test Lab cho các lần chạy hàng đêm trên top 10 thiết bị Android.
Câu hỏi thường gặp
Golden Test — để xác minh nhanh các thành phần UI riêng lẻ ở mỗi lần commit (50-200 ms). Screenshot Test — để xác minh E2E toàn bộ màn hình trên thiết bị thật trước khi phát hành (2-30 giây). Sử dụng cả hai: golden cho các thành phần Design System, screenshot cho các luồng người dùng quan trọng. Tỷ lệ 80/20 là tối ưu cho hầu hết các dự án.
SSIM 0.98 là ngưỡng khởi đầu tốt cho hầu hết các màn hình. Đối với chủ đề tối, bạn có thể sử dụng 0.99 (độ tương phản cao hơn — so sánh chính xác hơn). Đối với màn hình có gradient và hình ảnh — 0.95-0.97. Không sử dụng so sánh tuyệt đối từng pixel (MSE = 0) — nó tạo ra 20-30% kết quả dương tính giả do khử răng cưa và sự khác biệt GPU. Cấu hình ngưỡng riêng cho từng kiểm thử.
Với mỗi thay đổi UI có chủ đích — thay đổi màu sắc, phông chữ, lề, biểu tượng, thêm/xóa phần tử. Không cập nhật đường cơ sở khi môi trường thay đổi (phiên bản HĐH, phông chữ trên CI) — đây là dấu hiệu của kiểm thử không ổn định. Đường cơ sở chỉ được cập nhật cục bộ bởi nhà phát triển sau khi xem xét mã: xóa đường cơ sở cũ, chạy kiểm thử với record=true, kiểm tra ảnh chụp mới, commit.
Có — qua Espresso trên Android và XCUITest trên iOS. Espresso hoạt động bên trong tiến trình ứng dụng và không yêu cầu Accessibility Service (như UI Automator). XCUITest là framework tiêu chuẩn của Apple cho kiểm thử UI. Đối với screenshot test, sự khác biệt là tối thiểu: XCUITest ổn định hơn một chút (API gốc của Apple), UI Automator linh hoạt hơn một chút (tương tác liên tiến trình).
Nếu được cấu hình đúng — không. Trước khi merge: chỉ chạy screenshot test trên các màn hình đã thay đổi (30-60 giây). Hàng đêm: chạy đầy đủ trên Device Farm (30 phút, 20 thiết bị). Thời gian thực thi screenshot test trên trình giả lập: 2-10 giây mỗi màn hình. 20 màn hình = 40-200 giây. Điều này ít hơn thời gian kiểm thử thủ công một màn hình (5-10 phút).
Tóm tắt
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.
Đọc thêm