Skip to content

Assertion Login yang Tidak Pernah Gagal: Ketika URL Selalu Cocok

Adityo Guni Waluyo

Mengganti pemeriksaan rute dengan penanda visual pada fixture E2E untuk mendeteksi kegagalan login yang sebelumnya terlewat oleh sistem pengujian.

Ringkasan

Helper login E2E keliatannya aman karena ngecek URL /admincms, padahal rute itu sama aja mau login sukses atau gagal jadi tesnya nggak pernah merah. Akhirnya assertion diganti jadi ngecek chip admin yang cuma muncul kalau sesi beneran valid, jadi kalau gagal langsung ketahuan. Intinya assertion yang nggak bisa gagal tuh nggak ada gunanya sama sekali.

Saya sedang membaca frontend/e2e/support/fixtures.ts, helper login admin yang dipakai seluruh rangkaian test E2E, dan berhenti di baris terakhirnya: assertion hanya terhadap URL. Sekilas penjegaannya terlihat rapi — kalau login gagal, halaman tidak berpindah, test pasti langsung protes.

Yang luput: rute /admincms berfungsi ganda. Rute itu adalah layar pra-login sekaligus dasbor pascalogin, jadi kondisinya bernilai benar bahkan ketika kredensial admin development ditolak sistem. Assertion-nya tidak pernah gagal karena tidak pernah bisa gagal.

Saya sempat mengira helper itu dibuat terburu-buru; nyatanya seluruh spec memang bergantung padanya, dan justru assertion yang terlihat paling aman di situlah yang paling berbahaya karena tidak pernah memberi suara ketika login gagal.

Saya ganti baris itu dengan penanda keadaan yang hanya muncul setelah sesi valid terbentuk. Perubahan ini kecil, tapi prinsip di baliknya berlaku untuk assertion apa pun: sebuah assertion hanya bernilai seberapa besar ia mampu gagal.

Ulang otomatis bukan jaring pengaman

Playwright menyediakan kelas PageAssertions berisi assertion untuk keadaan halaman [5], dan toHaveURL memang salah satunya. Dokumentasinya sendiri memakai assertion URL setelah klik yang benar-benar mengubah rute, bukan untuk menunggu hasil login di rute yang tidak pernah berpindah.

Assertion di Playwright berulang otomatis: diambil ulang sampai kondisinya terpenuhi atau timeout tercapai [1]. Timeout tidak ikut bermain karena kondisinya sudah benar sejak detik pertama. Ulang otomatis hanya menolong kalau kondisi bisa berubah dari salah ke benar. Kalau rute sama persis di jalur sukses maupun gagal, berapa kali pun diulang, hasilnya tetap benar untuk tes yang gagal.

Best practices resminya juga menegaskan arah yang sama: test otomatis memverifikasi kode bagi pengguna akhir dan menghindari detail implementasi yang tidak dilihat pengguna [2]. Pengguna memang tidak menilai login dari URL di bilah alamat; mereka menilainya dari elemen yang muncul setelah berhasil masuk.

Penanda yang hanya muncul setelah sesi valid

Perbaikannya ada di diff fixture, empat baris berubah menjadi satu:


// Sebelum: assertion terhadap rute yang tidak pernah berubah
await expect(page).toHaveURL(/admincms/);

// Sesudah: menunggu penanda pascalogin
await expect(page.getByTestId('admin-user-chip')).toBeVisible();

admin-user-chip dirender oleh layout admin hanya kalau sesi sudah valid. Login gagal, elemennya tidak pernah muncul, dan test berhenti merah sebagaimana mestinya — bukan lolos karena rute yang selalu cocok.

Ada cara cepat memeriksa curiga semacam ini tanpa menulis test baru: jalankan skenario gagalnya, lalu lihat assertion mana yang tetap lolos. Kalau sesi dikosongkan atau kredensial ditolak sistem, dan sebuah assertion tetap hijau, assertion itu memang sedang tidak memverifikasi apa pun. Di jalur gagal, URL di fixture ini tetap menunjuk ke /admincms, sama persis dengan jalur sukses.

Variasi kegagalan yang sama sering muncul di fixture lain: assertion terhadap teks placeholder yang diisi framework, atau terhadap elemen yang memang selalu ada di halaman. Polanya sama: kondisi yang kebenarannya sudah dipastikan sejak awal.

data-testid bukan jalan pintas

Prinsip panduan Testing Library terkenal kalau test yang paling mirip dengan cara perangkat lunak dipakai memberi kepercayaan paling besar [3]. Karena itu urutan pilihan query-nya penting: cari berdasarkan peran atau teks yang dilihat pengguna lebih dulu, dan pakai data-testid hanya kalau keduanya tidak punya padanan yang stabil [4]. Saya tetap memakainya di sini, lebih baik daripada menggantungkan test pada struktur DOM atau nama kelas CSS yang bisa berubah kapan saja.

Ukuran praktisnya berlaku untuk assertion di mana pun: sebelum menaruh assertion, tanyakan dulu bentuknya seperti apa di jalur gagal. Assertion yang hasilnya identik di dua jalur bisa dihapus saja. Ia menambah baris test tanpa menambah kepercayaan, dan biayanya baru terasa ketika kegagalan nyata justru lolos tanpa suara.

Artikel fixture login sebelumnya membahas kenapa helper login dibuat terpisah dari spec: Fixture Dulu, Spec Kemudian. Baris yang saya ganti di artikel itu justru yang dulu terlihat paling aman, dan menurut saya itu bagian paling jujur dari kasus ini: kegagalan yang paling mahal bukan test yang berisik, melainkan test yang hening karena tidak pernah bisa gagal.

Sumber

[1] Playwright docs: Test assertions
[2] Playwright docs: Best practices
[3] Testing Library: Guiding principles
[4] Testing Library: getByTestId
[5] Playwright docs: PageAssertions

Artikel terkait