Nama test adalah kalimat yang muncul di laporan waktu test itu gagal. BDD (Behavior-Driven Development) mengajak kita menulis test sebagai perilaku: dalam kondisi apa, terjadi apa, hasilnya apa. Bayangin panel sekring listrik di rumah. Kalau labelnya cuma "1, 2, 3, 4", waktu listrik turun kamu harus coba satu per satu. Kalau labelnya "dapur", "kamar", "AC", kamu langsung tahu bagian mana yang mati. Nama test adalah label itu.
🧪 Tebakan cepat: test bernama
should throw when price is negativeada di dalamdescribe("Keranjang"), di filekeranjang.test.js. Kalau gagal, baris FAIL di laporan Vitest bunyinya apa? Jawabannya ada di bagian "describe dan it: nama yang bercerita".
Nama test dibaca waktu test gagal
Contoh di pelajaran ini: modul keranjang belanja dengan fungsi createCart(). Satu baris kodenya rusak, total harga lupa ditambah. Ini laporan Vitest (npx vitest run --reporter=verbose, mode yang menulis semua nama test) untuk dua versi nama:
× keranjang.test.js > testTotal 3ms
→ expected +0 to be 50000 // Object.is equality
× keranjang.test.js > Keranjang > should add the price to total when product is added 3ms
→ expected +0 to be 50000 // Object.is equality
×artinya test gagal,✓artinya lulus.expected +0 to be 50000artinya hasilnya 0 (Vitest menulis nol sebagai+0), padahal seharusnya 50.000.- Laporan pertama cuma bilang "testTotal gagal". Laporan kedua sudah kalimat: harga harus masuk ke total waktu produk ditambah. Kamu tahu apa yang rusak tanpa membuka file.
Given, When, Then
BDD memecah satu perilaku jadi tiga bagian, selalu dengan urutan ini:
- Given: kondisi awal. Keranjang masih kosong.
- When: aksi yang terjadi. User menambah "Buku" seharga 50.000.
- Then: hasil yang diharapkan. Keranjang berisi 1 barang.
Tim produk dan QA sering menulisnya dalam format Gherkin, bahasa biasa yang bisa dijalankan alat seperti Cucumber:
Feature: Keranjang belanja
Scenario: Menambah barang ke keranjang kosong
Given keranjang masih kosong
When user menambahkan "Buku" seharga 50000
Then keranjang berisi 1 barang
And totalnya 50000
Di Vitest, strukturnya dibawa sebagai komentar di dalam test:
import { describe, it, expect } from "vitest";
import { createCart } from "./keranjang";
describe("Keranjang", () => {
it("should add item to cart when valid product is given", () => {
// Given: keranjang kosong
const cart = createCart();
// When: user menambah Buku
cart.add({ name: "Buku", price: 50000 });
// Then: isinya 1 barang
expect(cart.items).toHaveLength(1);
});
});
describe("Keranjang", ...)mengelompokkan semua test milik keranjang.it("should ...", ...)adalah satu test. Teks pertamanya adalah nama yang muncul di laporan.- Tiga komentar memisahkan persiapan, aksi, dan pengecekan. Nama lainnya AAA: Arrange, Act, Assert. Isinya sama, cuma beda istilah.
Pola nama: should ... when ...
Pola paling umum: "should [hasil] when [kondisi]". Hasil dulu, lalu kondisinya.
it("should add item to cart when valid product is given");
it("should throw when price is negative");
it("should redirect to login when user is not authenticated");
Dua pola lain juga dipakai: "when cart is empty, checkout button is disabled" atau kalimat biasa "adds item to empty cart". Pilih satu untuk satu proyek, lalu konsisten.
Nama yang buruk punya ciri yang sama: gak menyebut kondisi atau hasil.
test1,cart,works: gak bilang apa-apa.handles request correctly: "correctly" itu yang mana?should call the redirect helper: menyebut cara kerja kode, bukan yang dialami user. Kalau helper-nya diganti, nama ini ikut bohong.
Dibanding nama-nama tadi, should redirect to login when user is not authenticated paling informatif: ada hasil (redirect ke login) dan kondisi (user belum login).
describe dan it: nama yang bercerita
Vitest menyambung nama file, nama describe, dan nama it dengan tanda >. Jadi test should throw when price is negative di dalam describe("Keranjang") muncul sebagai:
FAIL keranjang.test.js > Keranjang > should throw when price is negative
Itu jawaban tebakannya. Karena disambung, describe cukup berisi subjeknya ("Keranjang"), dan it cukup berisi perilakunya. Gak perlu menulis "Keranjang" lagi di tiap it.
Latihan: renameTest dan isGoodName
Latihannya meminta dua fungsi. renameTest(oldName) mengganti nama lama dengan nama BDD, dan isGoodName(name) mengecek apakah sebuah nama memuat kata should atau when.
const NAMA_BARU = {
test1: "should run first test case",
testAdd: "should add two numbers correctly",
cart: "should add item to cart when valid product is given",
};
function renameTest(oldName) {
return NAMA_BARU[oldName] || oldName;
}
function isGoodName(name) {
const text = name.toLowerCase();
return text.includes("should") || text.includes("when");
}
console.log(renameTest("cart")); // should add item to cart when valid product is given
console.log(isGoodName("should add item")); // true
console.log(isGoodName("when user clicks")); // true
console.log(isGoodName("test1")); // false
NAMA_BARUadalah object yang dipakai sebagai tabel: kuncinya nama lama, isinya nama baru.NAMA_BARU[oldName]mengambil isi tabel untuk kunci itu. Kalau kuncinya gak ada, hasilnyaundefined, dan|| oldNamemengembalikan nama lamanya.toLowerCase()menyamakan huruf, jadi"Should add"juga terhitung.includes("should")menjawabtruekalau kata itu ada di dalam teks.
⚠️ Jebakan yang sering ketemu
- Nama tanpa kondisi atau hasil.
worksatauedge caselulus pemeriksaan siapa pun, tapi gak membantu waktu gagal. - Nama yang gak cocok dengan isinya. Namanya bilang "should add item", tapi yang dicek
cart.total. Waktu gagal, laporannya menyesatkan. - Menyebut implementasi.
should call reducepatah begitu kodenya ditulis ulang, walau perilakunya sama. isGoodNamecuma cek satu kata. Nama"when user clicks"gak memuatshould, tapi tetap nama yang baik. Cek dua-duanya dengan||.
TL;DR: Nama test adalah kalimat yang kamu baca waktu test gagal, jadi tulis perilakunya: kondisi dan hasil, misalnya "should redirect to login when user is not authenticated". Struktur BDD: Given (kondisi awal), When (aksi), Then (hasil), selalu dalam urutan itu, sama dengan AAA (Arrange, Act, Assert). Vitest menyambung file, describe, dan it dengan >, jadi describe berisi subjek dan it berisi perilaku. Di latihan, renameTest memakai object sebagai tabel nama, dan isGoodName mengecek includes("should") || includes("when") setelah toLowerCase().