Lima Baseline Basi Sekaligus: Regen Visual Itu Keputusan
Lima hard failure serentak di halaman publik, semuanya visual baseline. Kapan regen --update-snapshots aman, dan kapan regen itu justru meresmikan bug.
Ringkasan
Test visual gagal di 5 halaman publik gara-gara perubahan UI. Jangan langsung regen baseline, karena --update-snapshots bisa meresmikan render rusak jadi patokan baru. Regen di lingkungan sama kayak CI, pakai mode changed, review tiap PNG yang berubah, lalu commit bareng snapshotnya.
Run suite penuh di repo portal KotaPortal makan 44,8 menit dengan 2 worker. Ringkasan akhirnya: 103 test passed, 9 flaky (lulus setelah retry), dan 5 hard failure. Kelima failure itu menempel persis di lima halaman publik: beranda dan empat halaman sektor. Semuanya test visual.
Lima failure dengan jenis yang sama, justru di halaman paling kelihatan. Refleks pertama saya sudah terbentuk sebelum log selesai terbaca: ini pasti baseline basi, tinggal regen.
Lima failure yang menempel di halaman publik
Playwright menyimpan screenshot referensi sebagai file PNG di folder <spec-file>-snapshots/, dengan nama berdasarkan judul test, browser, dan platform — contohnya home-chromium-linux.png. Perbandingan visualnya sendiri pakai await expect(page).toHaveScreenshot(): pada eksekusi pertama Playwright membuat referensi, dan run berikutnya membandingkan render terhadap referensi itu [1].
Saat test gagal, pesan kelimanya pola yang sama: screenshot aktual berbeda dari ekspektasi. Wajar, karena memang ada perubahan frontend yang sah dikirim lebih dulu oleh program yang sama: menu header baru, breadcrumb baru, dan satu halaman baru. Kelima halaman yang gagal kebetulan memakai komponen-komponen itu.
Tapi di titik inilah saya berhenti sebelum mengetik perintah apa pun. “Perubahan UI sudah dikirim” bukan bukti bahwa perubahannya benar.
Salah kira: perubahan UI membuat baseline otomatis basi
Salah kira yang umum di sini: begitu tahu ada perubahan UI, failure visual otomatis dianggap basi. Padahal --update-snapshots tidak memvalidasi apa pun. Flag itu menulis render saat ini sebagai kebenaran baru [1]. Kalau perubahan yang dikirim itu rusak — header terpotong, breadcrumb menimpa konten, layout lompat — regen akan meresmikan render yang rusak itu sebagai baseline. Suite kembali hijau, dan kerusakannya lolos ke produksi tanpa jejak.
Dokumentasi Playwright sendiri menyatakan bahwa folder snapshot sebaiknya di-commit ke version control dan setiap perubahannya direview [1]. Kalimat “review any changes” itu berlaku untuk regen juga, bukan hanya untuk perubahan kode.
Ada satu jebakan lain: rendering browser bervariasi menurut OS, versi, hardware, sumber daya (baterai versus adapter), mode headless, dan faktor lain [1]. Kalau baseline dibuat di satu lingkungan dan regen dijalankan di lingkungan lain, diff yang muncul bisa murni artefak rendering. Percuma mereview PNG yang sejak awal dibandingkan di lingkungan yang salah.
Regen yang aman adalah regen yang direview
Prosedur yang saya pakai, urut:
- Pastikan regen dijalankan di lingkungan yang sama dengan tempat baseline hidup. Di repo ini, lingkungannya Linux headless yang sama dengan CI. Jangan regen dari laptop dengan OS berbeda.
- Jalankan regen dengan mode eksplisit, bukan mengandalkan default:
npx playwright test --update-snapshots=changed- Review setiap PNG yang berubah seperti review diff kode. Buka file lama dan file baru berdampingan, dan tanya satu hal: apakah diff-nya hanya di area yang memang berubah (header, breadcrumb), atau ada perubahan lain yang tidak pernah saya minta? Kalau layout di luar area perubahan ikut bergeser, itu bukan baseline basi. Itu bug.
- Commit test dan folder snapshot dalam commit yang sama. Snapshot adalah bagian dari spesifikasi, bukan artefak build yang boleh terpisah.
- Verifikasi dengan run penuh tanpa flag. Di kasus ini run kedua menghasilkan visual test hijau dalam 38 detik, lalu 27 detik pada run berikutnya.
Flag --update-snapshots menerima lima nilai mode: all, changed, missing, none, default. Tanpa flag, perilaku regennya default; begitu flag ditulis tanpa nilai, nilainya changed [3]. Saya selalu menulis nilai mode itu secara eksplisit supaya niatnya terbaca di riwayat command.
Catatan mekanisnya: toHaveScreenshot() menunggu dua screenshot berurutan menghasilkan hasil yang sama sebelum membandingkan, jadi render yang masih bergerak atau flaky sudah disaring sebelum perbandingan terjadi [2]. Kalau failure tetap muncul setelah dua kali run stabil, perbedaannya nyata, bukan noise.
Kenapa aturan ini perlu? Karena baseline visual adalah spesifikasi desain yang bisa dieksekusi. Menjalankan --update-snapshots sama dengan mengubah spesifikasi. Perubahan spesifikasi yang tidak direview bukan regenerasi, melainkan penghapusan pengawasan.
Sources
[1] Visual comparisons - Playwright