Episode ini membahas cara menangkap baseline screenshot, membandingkan visual diff dengan toHaveScreenshot, menoleransi layout drift dengan thresholding, serta integrasi dengan tool visual regression untuk pengawasan tampilan yang konsisten.

Bug visual adalah jenis bug yang paling mudah lolos dari test fungsional: layout bergeser satu pixel, warna salah, atau elemen bertumpuk — semua tidak akan tertangkap oleh assertion teks biasa. Episode 16 ini membahas visual regression testing: membandingkan tampilan aplikasi dengan baseline untuk mendeteksi perubahan visual yang tidak disengaja.
Playwright menyediakan snapshot testing bawaan melalui expect(page).toHaveScreenshot(). Kalian akan belajar menangkap baseline, memahami cara kerja perbandingan pixel, mengelola perubahan yang disengaja, dan menangani tantangan nyata seperti font dan animasi yang membuat perbandingan rapuh.
Screenshot baseline diambil otomatis pada lari pertama:
import { test, expect } from '@playwright/test';
test('halaman beranda sesuai baseline', async ({ page }) => {
await page.goto('/beranda');
await expect(page).toHaveScreenshot('beranda.png');
});Pada eksekusi pertama, toHaveScreenshot('beranda.png') menyimpan gambar sebagai baseline di folder __screenshots__. Eksekusi berikutnya membandingkan screenshot baru dengan baseline tersebut; perbedaan pixel akan menggagalkan test.
Tidak selalu perlu membandingkan seluruh halaman — elemen tertentu lebih stabil dan lebih mudah di-diff:
await expect(page.getByRole('card', { name: 'Produk Unggulan' }))
.toHaveScreenshot('kartu-produk.png');toHaveScreenshot pada locator membatasi area perbandingan ke elemen tersebut. Ini mengurangi noise dari bagian halaman yang sering berubah — misalnya iklan atau widget waktu — sekaligus menegaskan area yang paling penting.
Baseline disimpan di repository dan harus di-commit. Susunan foldernya mengikuti struktur test, jadi setiap file spec memiliki folder snapshotnya sendiri. Saat baseline berubah karena perubahan desain yang memang disengaja, kalian memperbaruinya secara eksplisit.
Ketika perubahan visual memang disengaja — misalnya rilis desain baru — perbarui baseline:
npx playwright test --update-snapshots--update-snapshots menimpa baseline dengan screenshot terbaru. Gunakan flag ini hanya saat kalian yakin perubahan itu benar, bukan untuk menutupi bug.
Alur yang sehat: saat test gagal karena visual diff, buka screenshot aktual dan bandingkan dengan baseline. Jika perubahan memang diinginkan, update baseline dan sertakan dalam commit dengan catatan. Jika tidak, selidiki penyebabnya — mungkin CSS yang baru saja berubah.
Perbandingan pixel yang terlalu ketat akan mudah gagal karena anti-aliasing, rendering font lintas platform, atau sub-pixel rendering. Playwright menyediakan opsi maxDiffPixelRatio dan maxDiffPixels untuk menoleransi perbedaan kecil:
test('halaman checkout sesuai baseline', async ({ page }) => {
await page.goto('/checkout');
await expect(page).toHaveScreenshot('checkout.png', {
maxDiffPixelRatio: 0.01,
});
});maxDiffPixelRatio: 0.01 mengizinkan hingga 1 persen pixel berbeda sebelum dianggap gagal. Nilai yang tepat perlu diuji pada environment CI kalian — terlalu besar akan melewatkan bug nyata.
Salah satu tantangan terbesar visual regression: baseline dibuat di lokal, dijalankan di CI — dan hasil rendering bisa berbeda karena font dan OS. Solusi umum:
page.emulateMedia({ reducedMotion: 'reduce' }) agar frame stabil.await page.emulateMedia({ reducedMotion: 'reduce' });
await page.goto('/beranda');
await expect(page).toHaveScreenshot('beranda.png');page.emulateMedia({ reducedMotion: 'reduce' }) menyuruh halaman memakai preferensi reduced motion, mencegah animasi yang mengubah frame di antara screenshot.
Untuk halaman beranimasi, tunggu animasi selesai sebelum snapshot — atau matikan animasi lewat opsi CSS. Menunggu elemen hasil (misalnya class yang menandai animasi selesai) lebih andal daripada menebak durasi.
Playwright native sudah mencukupi untuk sebagian besar kebutuhan. Tool eksternal seperti Percy menawarkan kemampuan tambahan: perbandingan cerdas yang fokus pada perubahan makna visual (bukan pixel mentah), management dashboard, dan baseline approval yang terpusat.
Integrasi dengan tool seperti Percy umumnya mengikuti pola snapshot yang serupa:
import percySnapshot from '@percy/playwright';
test('halaman beranda', async ({ page }) => {
await page.goto('/beranda');
await percySnapshot(page, 'Beranda');
});percySnapshot(page, 'Beranda') mengirim snapshot ke dashboard Percy untuk perbandingan dan approval. Snapshot dikirim dalam CI mode sehingga tidak mengganggu test lokal.
Pertimbangkan tool eksternal saat: tim besar perlu proses approval visual yang terpusat, aplikasi sangat bergantung pada tampilan, atau kalian butuh historical comparison lintas banyak rilis. Untuk tim kecil yang ingin solusi sederhana, snapshot native Playwright sudah cukup.
npx playwright test tests/visual.spec.tsEpisode 16 membuat tampilan aplikasi diawasi secara otomatis: baseline screenshot ditangkap dan di-commit, perbandingan toHaveScreenshot mendeteksi perubahan pixel, thresholding menoleransi rendering noise, dan tool eksternal memberikan approval terpusat untuk skala tim yang lebih besar.
Inti yang harus dibawa pulang:
toHaveScreenshot menyimpan baseline dan membandingkannya di lari berikutnya.maxDiffPixelRatio menoleransi perbedaan rendering tanpa menutupi bug.reducedMotion dan font konsisten menjaga snapshot stabil antar environment.Di episode 17 selanjutnya kita akan membahas accessibility testing — pemeriksaan aksesibilitas otomatis dengan integrasi axe-core, validasi ARIA roles dan labels, pengujian keyboard navigation, serta menambahkan assertion aksesibilitas ke regression suite.