BDD & Penamaan Test — Testing

Test adalah Dokumentasi Hidup Test bukan cuma untuk mencegah bug — test adalah dokumentasi yang dieksekusi. Developer baru membaca nama test untuk mengerti…

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 negative ada di dalam describe("Keranjang"), di file keranjang.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

Given, When, Then

BDD memecah satu perilaku jadi tiga bagian, selalu dengan urutan ini:

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);
  });
});

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.

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

⚠️ Jebakan yang sering ketemu

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().

Yang akan kamu pelajari