Snapshot testing adalah metode pemeriksaan otomatis antarmuka pengguna, di mana keadaan layar saat ini dibandingkan dengan gambar referensi (snapshot) yang disimpan pada proses uji sebelumnya. Setiap perbedaan visual dicatat sebagai perubahan yang memerlukan konfirmasi pengembang. Berbeda dengan uji UI yang memeriksa keberadaan elemen, uji snapshot mencatat perubahan piksel — pergeseran, penyimpangan warna, dan gangguan tata letak. Menurut Android Developers, 2024, snapshot testing mendeteksi hingga 30% regresi visual yang terlewatkan oleh uji UI tradisional, menjadikannya alat yang sangat diperlukan untuk mempertahankan antarmuka yang konsisten.
Poin Utama
Snapshot testing adalah teknik di mana uji me-render komponen antarmuka, menyimpan gambar yang diperoleh sebagai referensi, dan pada proses selanjutnya membandingkan render saat ini dengan referensi ini. Jika gambar cocok — uji lulus. Jika ditemukan perbedaan — uji gagal, dan pengembang menerima gambar diff dengan piksel yang berubah disorot. Teknik ini diadopsi dari pengembangan web (Jest snapshots) dan diadaptasi untuk platform seluler.
Nilai utama uji snapshot adalah deteksi otomatis perubahan visual yang tidak terduga. Pengembang dapat mengubah skema warna dalam tema global dan secara tidak sengaja memengaruhi puluhan layar. Uji UI yang memeriksa keberadaan tombol dan teks tidak akan melihat ini. Uji snapshot akan mencatat perubahan setiap piksel pada setiap layar yang terpengaruh, memberikan gambaran lengkap tentang dampak perubahan.
Menurut survei Mobile DevOps Summit 2023, tim yang menggunakan snapshot testing di samping uji UI klasik mengurangi jumlah cacat visual dalam rilis sebesar 40%. Pendekatan ini sangat efektif dalam proyek dengan sistem desain dan pendekatan berbasis komponen, di mana perubahan satu komponen dasar dapat memengaruhi puluhan layar aplikasi.
Perbedaan mendasar terletak pada objek pemeriksaan. Uji UI memeriksa keberadaan, status, dan perilaku elemen antarmuka: “tombol terlihat”, “teks berisi pesan kesalahan”, “setelah diklik, layar baru terbuka”. Uji snapshot memeriksa tampilan secara keseluruhan: penempatan elemen, jarak, warna, font, bayangan, dan pembulatan. Uji snapshot menjawab pertanyaan “apakah layar terlihat seperti yang diharapkan?”, sedangkan uji UI — “apakah layar berfungsi seperti yang diharapkan?”
Kecepatan eksekusi juga berbeda. Uji UI dijalankan pada emulator atau perangkat nyata, memerlukan pemuatan penuh aplikasi dan memakan waktu 10 detik hingga satu menit per skenario. Uji snapshot yang didasarkan pada library seperti Paparazzi me-render komponen di lingkungan virtual tanpa menjalankan emulator, mengurangi waktu uji menjadi 100–500 milidetik. Satu set lengkap uji snapshot (50–100 layar) dijalankan dalam 2–5 menit, bukan 30–60 menit untuk set uji UI yang serupa.
Namun uji snapshot tidak menggantikan uji UI. Strategi optimal adalah kombinasi: uji snapshot mencakup regresi visual (render setiap layar dalam keadaan dasar), dan uji UI mencakup regresi perilaku (skenario klik, validasi input, navigasi). Kombinasi semacam itu memberikan 90% keyakinan akan kebenaran antarmuka dengan waktu eksekusi CI yang minimal.
Di Android, alat utamanya adalah Paparazzi dan Shot. Paparazzi dari Cash App me-render komponen di lingkungan uji pada JVM tanpa emulator, menggunakan tata letak gravitasi Layoutlib. Shot dari Karumi mengambil tangkapan layar Instrumentasi pada perangkat nyata atau emulator dan membandingkannya dengan referensi melalui library AShot, memperhitungkan perbedaan resolusi dan kerapatan piksel.
Paparazzi tidak memerlukan menjalankan emulator — render dilakukan pada JVM melalui Layoutlib, yang memberikan kecepatan sebanding dengan uji unit. Library mendukung baik sistem View maupun Jetpack Compose. Untuk Compose digunakan pengubah paparazzi.snapshot { MyComposable() }. Referensi disimpan di src/test/snapshots dan secara otomatis dibandingkan pada setiap proses. Persentase perbedaan maksimum dikonfigurasi melalui maxPercentDifference.
SnapshotTesting dari Point-Free mendukung perbandingan tidak hanya UIImage, tetapi juga string, JSON, Data, dan seluruh penyimpanan Core Data. Ini menjadikannya alat universal tidak hanya untuk snapshot UI, tetapi juga untuk memeriksa serialisasi dan decoding respons JSON. Untuk SwiftUI digunakan ekstensi assertSnapshot dengan pengubah .image(on: .iPhone13). Strategi perekaman — record: true — membuat referensi pada proses pertama.
Untuk React Native, solusi populer adalah react-native-testing-library dalam kombinasi dengan jest-image-snapshot. Pendekatan web untuk snapshot testing dibawa ke lingkungan seluler melalui render komponen di lingkungan Node.js dengan perbandingan berikutnya dari snapshot JSON DOM virtual. Pendekatan ini lebih cepat dari native, tetapi kurang akurat — tidak memperhitungkan fitur platform dalam render font dan komponen sistem. Untuk Flutter digunakan golden testing melalui goldens toolkit.
Mari kita lihat uji snapshot untuk Android (Paparazzi) dan iOS (SnapshotTesting). Kedua contoh memeriksa tampilan komponen — kartu pengguna dengan avatar, nama, dan status. Uji me-render komponen dengan data uji dan membandingkan hasilnya dengan gambar referensi yang disimpan di repositori.
Paparazzi menggunakan anotasi @Test dan metode snapshot() untuk menangkap render. Referensi disimpan di folder src/test/snapshots dan secara otomatis diambil pada proses berikutnya untuk perbandingan.
class UserCardSnapshotTest {
@get:Rule
val paparazzi = Paparazzi(
theme = "Theme.MyApp",
maxPercentDifference = 0.1
)
@Test
fun userCard_defaultState() {
val card = UserCard(
name = "Alice Johnson",
status = "Online",
avatarUrl = "https://example.com/avatar.png"
)
paparazzi.snapshot(card)
}
@Test
fun userCard_offlineState() {
val card = UserCard(
name = "Bob Smith",
status = "Offline",
avatarUrl = null
)
paparazzi.snapshot(card, name = "user_card_offline")
}
}
SnapshotTesting menggunakan pengubah .snapshot() di dalam assertSnapshot. Library secara otomatis menentukan format — UIImage untuk UIView, String untuk teks, Data untuk data biner.
import SnapshotTesting
import XCTest
class UserCardSnapshotTests: XCTestCase {
func testUserCardDefaultState() {
let card = UserCardView(
name: "Alice Johnson",
status: "Online",
avatarURL: URL(string: "https://example.com/avatar.png")
)
let controller = UIHostingController(rootView: card)
assertSnapshot(matching: controller, as: .image(on: .iPhone13))
}
func testUserCardOfflineState() {
let card = UserCardView(
name: "Bob Smith",
status: "Offline",
avatarURL: nil
)
assertSnapshot(matching: card, as: .image(on: .iPhone13))
}
}
Alur kerja tipikal mencakup empat tahap. Proses pertama (record mode): semua uji snapshot dijalankan dalam mode perekaman — gambar referensi dibuat dan disimpan di repositori. Tahap ini dilakukan pada pengaturan awal uji atau setelah perubahan antarmuka yang disengaja. Setelah perekaman, referensi di-commit bersama dengan kode — mereka menjadi bagian dari proyek.
Pada proses selanjutnya, uji bekerja dalam mode perbandingan: setiap render baru dibandingkan dengan referensi. Jika ditemukan perbedaan, gambar diff dihasilkan: piksel yang cocok dengan referensi disorot hijau, yang berbeda disorot merah. Pengembang mempelajari diff dan mengambil keputusan: jika perubahan diharapkan (perubahan desain yang disengaja), referensi diperbarui dengan perintah record; jika tidak terduga — bug diperbaiki. Memperbarui referensi dilakukan dengan perintah satu kali: untuk Paparazzi yaitu `./gradlew recordPaparazzi`, untuk SnapshotTesting — `assertSnapshot(record: true)`.
Menurut Spotify Engineering Blog (2022), tim yang menggunakan alur kerja yang dijelaskan menghabiskan rata-rata 2 menit per uji untuk menganalisis gambar diff. Pada set 50 uji snapshot, siklus pembaruan referensi lengkap memakan waktu 15–20 menit, yang secara signifikan lebih cepat daripada verifikasi manual perubahan visual pada 50 layar.
Uji snapshot memiliki keterbatasan mendasar. Kepekaan terhadap lingkungan: komponen yang sama dapat di-render berbeda pada versi OS yang berbeda, kerapatan layar, dan konfigurasi font. Referensi yang dibuat pada satu mesin dapat berbeda dari render di server CI. Solusinya — menggunakan parameter lingkungan tetap: versi Layoutlib tertentu untuk Paparazzi atau model perangkat yang tepat untuk SnapshotTesting.
Antipola No. 1: snapshot raksasa — uji snapshot yang menangkap seluruh layar gagal pada setiap perubahan minimal komponen apa pun. Pendekatan yang benar — menguji komponen individual (tombol, kartu, bidang input) secara terisolasi. Setiap komponen diuji secara independen, memberikan indikasi yang tepat tentang sumber perubahan. Antipola No. 2: mengabaikan diff — pembaruan referensi otomatis tanpa analisis gambar diff mengurangi nilai uji snapshot menjadi nol. Setiap diff memerlukan keputusan sadar dari pengembang.
Menurut Better Engineering Blog (2023), uji snapshot memberikan manfaat terbesar saat mencakup komponen sistem desain dan layar kunci dalam keadaan dasar — kosong, terisi, error, dan batas. Mencakup animasi dan keadaan dinamis melalui uji snapshot tidak efisien karena ketidakpastian stempel waktu dalam render — untuk skenario seperti itu, perekaman video atau pemeriksaan QA manual lebih cocok.
Pertanyaan Umum
Tidak, uji snapshot memeriksa tampilan, sedangkan uji UI memeriksa perilaku antarmuka. Strategi optimal adalah menggabungkan kedua pendekatan: snapshot untuk regresi visual, uji UI untuk memeriksa skenario dan navigasi. Snapshot menjawab pertanyaan “apakah terlihat benar?”, uji UI — “apakah berfungsi dengan benar?”
Referensi diperbarui pada setiap perubahan desain yang disengaja: warna tema baru, jarak yang diubah, penambahan atau penghapusan elemen. Pembaruan dilakukan melalui mode record, setelah itu gambar diff diperiksa dalam code review untuk memastikan perubahan sesuai dengan harapan desainer.
Pertama-tama, komponen sistem desain — tombol, kartu, bidang input, jendela modal. Kemudian layar kunci dalam keadaan dasar. Jangan uji dengan snapshot animasi, WebView, peta, dan layar dengan konten dinamis — untuk ini, snapshot memberikan kesalahan palsu karena ketidakpastian.
Gunakan API Level yang sama untuk mode record dan test. Untuk Paparazzi tetapkan versi Layoutlib tertentu dalam konfigurasi. Untuk SnapshotTesting tetapkan model perangkat. Referensi yang dibuat di Android 14 dapat berbeda dari render di Android 12 karena perubahan pada font sistem dan tema Material.
Di CI, uji snapshot dijalankan dalam mode verifikasi (verify). Jika uji gagal, CI menunjukkan gambar diff di artefak build. Mode record (pembaruan referensi) dilakukan secara lokal oleh pengembang atau dalam tugas CI terpisah dengan pemicu manual. Gambar referensi harus di-commit ke repositori.
Kesimpulan
Kami akan mengembangkan aplikasi seluler turnkey
IT Sectr membuat aplikasi iOS dan Android untuk startup dan bisnis sejak 2017. Kami akan memberi saran dan mengusulkan solusi terbaik.
Baca juga