Tes: jaring pengamanmu
Tes adalah kode yang memeriksa apakah kode lain melakukan apa yang kamu harapkan. Setelah ditulis, ia berjalan dalam hitungan detik dan langsung memberitahumu jika ada yang mundur (regresi).
Kumpulan tes yang sehat berbentuk seperti piramida: banyak sekali unit test kecil dan cepat di dasar, lebih sedikit integration test di tengah, dan hanya segelintir end-to-end test yang lambat di puncak. Sebagian besar keamananmu didapat dengan murah dari bagian bawah:
╱╲
╱ ╲ E2E few · slow · whole app
╱────╲ (end-to-end)
╱ ╲
╱ INTEG ╲ INTEGRATION some · medium
╱──────────╲ (parts together)
╱ ╲
╱ UNIT ╲ UNIT many · fast · one function
╱────────────────╲
cheap base = most of your tests
Kamu tidak butuh cakupan 100%. Mulailah dengan menguji hal-hal yang paling menyakitkan jika rusak: login, pembayaran, data yang tidak bisa dibuat ulang, logika bisnis inti. AI sangat andal dalam menulis tes — sering kali lebih baik daripada menulis fitur, karena perilaku yang diharapkan sudah konkret.
Berikut yang bekerja dengan baik:
Write tests for the calculateDiscount function in src/pricing.js.
Cover: a normal case, the zero/empty case, the maximum-discount
boundary, and one invalid input. Use the existing test setup in
this repo (check how other *.test.js files are structured).
Run the tests and show me they pass before you finish.
Baris terakhir itu penting. Selalu minta AI untuk menjalankan tesnya, bukan sekadar menulisnya. Tes yang tidak pernah dijalankan hanyalah tebakan. Penting juga untuk spesifik tentang kasus mana yang harus dicakup, karena kalau dibiarkan begitu saja, AI cenderung menulis tiga variasi dari jalur normal dan menyebutnya menyeluruh. Kasus-kasus yang benar-benar menangkap bug adalah yang membosankan: input kosong, nilai batas, hal yang seharusnya melempar error (throw).
Contoh sederhana dari apa yang seharusnya dihasilkan:
import { calculateDiscount } from "./pricing.js";
import { describe, it, expect } from "vitest";
describe("calculateDiscount", () => {
it("applies a normal percentage discount", () => {
expect(calculateDiscount(100, 0.2)).toBe(80);
});
it("returns the full price when discount is zero", () => {
expect(calculateDiscount(100, 0)).toBe(100);
});
it("never discounts below zero", () => {
expect(calculateDiscount(100, 1.5)).toBe(0);
});
it("rejects a negative price", () => {
expect(() => calculateDiscount(-10, 0.2)).toThrow();
});
});
Saat kamu mengubah sebuah fitur nanti, jalankan tes terlebih dahulu. Kalau berubah jadi merah, kamu menemukan kerusakan itu sebelum penggunamu menemukannya. Ketika AI memperbaiki sebuah bug, minta ia untuk menambahkan tes yang gagal pada perilaku lama — dengan begitu bug itu tidak bisa diam-diam kembali. Kebiasaan ini punya nama: regression test (tes regresi). Setiap bug yang kamu temui adalah pelajaran yang sudah dibayar mahal oleh codebase-mu; regression test adalah cara kamu menyimpan pelajaran itu.
Satu peringatan: sebuah tes juga bisa salah. Kalau AI menulis tes yang menyatakan perilaku yang buruk itu benar, tes itu akan lolos selamanya sementara aplikasimu tetap rusak. Jadi baca asersinya (assertion), bukan cuma tanda centang hijaunya. Tes yang lolos hanya berarti "kode melakukan apa yang dikatakan tes" — kamu tetap harus memastikan tesnya mengatakan hal yang benar.