Unit test & table-driven test
Uji fungsi otomatis dengan paket testing.
Pahami konsepnya
Tes Go hidup di berkas berakhiran _test.go di samping kode yang diuji. Setiap tes adalah fungsi bernama TestXxx (awalan Test wajib) yang menerima *testing.T. Jalankan semuanya dengan go test ./... — hasilnya lulus/gagal per paket, plus go test -v untuk rincian.
Kegagalan dilaporkan lewat t.Error / t.Errorf (menandai gagal tapi lanjut) atau t.Fatal / t.Fatalf (berhenti di titik itu). Assert bawaan memang tak ada — pola idiomatisnya if hasil != harapan { t.Errorf(...) } yang menampilkan dua nilai bersebelahan.
Bentuk dewasa di komunitas Go: table-driven test — semua kasus didefinisikan sebagai slice struct {nama, masukan, harapan}, lalu satu loop menjalankan semuanya lewat t.Run(nama, ...) yang membuat subtes terpisah. Menambah kasus baru cukup menambah baris tabel, tanpa menyalin logika. Subtes bisa dijalankan tunggal: go test -run TestBagi/pembagi_nol.
Coba contoh kode
package matematik
import "testing"
func Bagi(a, b int) (int, error) {
if b == 0 {
return 0, ErrPembagiNol
}
return a / b, nil
}
var ErrPembagiNol = errPembagiNol{}
type errPembagiNol struct{}
func (errPembagiNol) Error() string { return "pembagi tidak boleh nol" }
func TestBagi(t *testing.T) {
hasil, err := Bagi(10, 2)
if err != nil || hasil != 5 {
t.Errorf("Bagi(10,2) = %d, %v; ingin 5, nil", hasil, err)
}
}Berkas matematik_test.go menguji fungsi di paket yang sama. t.Errorf menandai kegagalan TANPA menghentikan tes — beberapa kasus bisa diperiksa berurutan dan semuanya terlapor sekali jalan. Pesannya mencantumkan hasil dan harapan agar kegagalan langsung terbaca penyebabnya.
Table-driven test
func TestBagiTabel(t *testing.T) {
kasus := []struct {
nama string
a, b, harapan int
inginError bool
}{
{"biasa", 10, 2, 5, false},
{"tak bulat", 7, 2, 3, false},
{"pembagi nol", 7, 0, 0, true},
{"negatif", -9, 3, -3, false},
}
for _, k := range kasus {
t.Run(k.nama, func(t *testing.T) {
hasil, err := Bagi(k.a, k.b)
if k.inginError && err == nil {
t.Fatalf("%s: ingin error, dapat %d", k.nama, hasil)
}
if !k.inginError && hasil != k.harapan {
t.Errorf("%s: dapat %d, ingin %d", k.nama, hasil, k.harapan)
}
})
}
}Empat kasus hidup dalam satu tabel; loop menjalankan masing-masing sebagai subtes bernama. Kasus "pembagi nol" menguji jalur error eksplisit — error yang DIHARAPkan adalah bagian kontrak fungsi, bukan kecelakaan. Tambahkan kasus baru dengan menambah baris, dan -run memungkinkan mengeksekusi hanya satu.
Latihan singkat
Uji: jalankan empat kasus pada tabel dan bandingkan dengan harapan — program harus mencetak persis `4/4 lulus`.