Semakin besar program, semakin mudah satu perubahan merusak perilaku di tempat lain tanpa terasa. Unit test menjawab masalah tersebut: program kecil yang memanggil fungsi Anda, membandingkan hasilnya dengan nilai yang diharapkan, lalu melaporkan setiap ketidakcocokan secara otomatis. Go membawa budaya ini sejak awal — perintah go test dan package testing tersedia bawaan, tanpa framework pihak ketiga. Pada chapter ini kita menulis test pertama untuk kalkulator mini, menjalankannya dengan beberapa variasi perintah, lalu membedah outputnya ketika lulus maupun gagal.
Menulis Test Pertama #
Kode produksi kita berisi dua fungsi aritmetika sederhana pada berkas kalkulator.go:
package main
// Tambah mengembalikan hasil penjumlahan a dan b.
func Tambah(a, b int) int {
return a + b
}
// Kali mengembalikan hasil perkalian a dan b.
func Kali(a, b int) int {
return a * b
}Test ditulis pada berkas terpisah berakhiran _test.go. Berkas test berada di package yang sama dengan kode produksi — di sini keduanya package main — sehingga test dapat memanggil Tambah dan Kali langsung. Perintah go build mengabaikan berkas _test.go; hanya go test yang mengompilasi berkas tersebut ke dalam binary test. Berikut isi kalkulator_test.go:
package main
import "testing"
func TestTambah(t *testing.T) {
got := Tambah(2, 3)
want := 5
if got != want {
t.Errorf("Tambah(2, 3) = %d; want %d", got, want)
}
}
func TestKali(t *testing.T) {
got := Kali(4, 6)
want := 24
if got != want {
t.Errorf("Kali(4, 6) = %d; want %d", got, want)
}
}Mari kita telaah baris demi baris berkas test di atas:
- Baris 1 (
package main): menempatkan berkas test pada package yang sama dengankalkulator.go, sehingga seluruh fungsi produksi dapat dipanggil langsung. - Baris 3 (
import "testing"): mengimpor packagetestingyang menyediakan tipetesting.Tsebagai perantara pelaporan kegagalan. - Baris 5 (
func TestTambah(t *testing.T)): mendeklarasikan fungsi test. Nama fungsi harus diawaliTestdiikuti huruf kapital agargo testmenjalankannya; parametertbertipe*testing.T. - Baris 6-7 (
gotdanwant): variabelgotmenyimpan hasil aktualTambah(2, 3), variabelwantmenyimpan nilai yang diharapkan. Pemisahan keduanya membuat pesan kegagalan mudah dibaca. - Baris 8-10 (
if+t.Errorf): ketikagottidak sama denganwant,t.Errorfmencatat kegagalan dengan format verb%d— dan test tetap berlanjut sampai fungsi selesai. - Baris 13-19 (
TestKali): mengulangi pola yang sama untukKali. Satu fungsi produksi diuji satu fungsi test terpisah agar kegagalan keduanya tidak saling menyamarkan.
Menjalankan go test #
Dari direktori chapter, jalankan:
go test -v ./...Output yang Dihasilkan:
=== RUN TestTambah
--- PASS: TestTambah (0.00s)
=== RUN TestKali
--- PASS: TestKali (0.00s)
PASSFlag -v meminta go test mencetak setiap test yang berjalan: baris === RUN menandai awal test, --- PASS menandai test yang lulus, dan angka (0.00s) adalah durasi test tersebut. Tanpa -v, go test hanya mencetak satu baris ringkasan per package; pada proyek situs ini barisnya berbunyi ok tutorial-website/content/go/testing/unit-test 0.002s.
Menjalankan go test dua kali tanpa perubahan kode menghasilkan tanda (cached) karena Go menyimpan hasil test pada cache. Gunakan go clean -testcache atau flag -count=1 untuk memaksa eksekusi ulang.
Menyaring Test dengan -run #
Flag -run menerima pola regular expression dan hanya menjalankan test yang namanya cocok:
go test -v -run TestTambah ./...Output yang Dihasilkan:
=== RUN TestTambah
--- PASS: TestTambah (0.00s)
PASSHanya TestTambah yang berjalan; TestKali tidak muncul. Pola -run TestTambah juga mencocokkan nama berawalan sama seperti TestTambahNegatif, jadi tambahkan pengikat seperti "^TestTambah$" bila ingin cocokan persis. Kombinasi -run dan -v adalah alat utama mempercepat siklus edit-lalu-uji.
Membaca Output Ketika Test Gagal #
Bentuk output kegagalan paling mudah dipahami lewat eksperimen kecil. Ubah sementara baris 5 kalkulator.go dari return a + b menjadi return a + b + 1, jalankan go test -v ./..., lalu kembalikan. Fungsi Tambah kini mengembalikan 6 untuk input 2 dan 3, sehingga TestTambah gagal:
Output yang Dihasilkan:
=== RUN TestTambah
kalkulator_test.go:9: Tambah(2, 3) = 6; want 5
--- FAIL: TestTambah (0.00s)
=== RUN TestKali
--- PASS: TestKali (0.00s)
FAILBaris kalkulator_test.go:9: menunjukkan berkas dan nomor baris pemanggilan t.Errorf — baris 9, tempat t.Errorf berada di dalam TestTambah. TestKali tetap berjalan setelah kegagalan tersebut karena t.Errorf hanya mencatat masalah tanpa menghentikan eksekusi. Ringkasannya:
| Kondisi hasil | Baris ringkasan | Exit status |
|---|---|---|
| Semua test lulus | ok <path-paket> <durasi> | 0 |
| Ada test gagal | FAIL <path-paket> <durasi> | 1 |
| Kode tidak berubah sejak run lalu | ok <path-paket> (cached) | 0 |
Exit status 1 membuat go test gagal pada pipeline CI maupun skrip build, sehingga test rusak langsung terlihat sebelum rilis.
t.Errorf vs t.Fatalf #
t.Errorf mencatat pesan lalu melanjutkan eksekusi test; t.Fatalf mencatat pesan lalu menghentikan fungsi test saat itu juga. Perbedaannya terlihat pada fragmen berikut:
func TestHitung(t *testing.T) {
got, err := Hitung("2+3")
if err != nil {
// hasil akhir tidak bisa dipercaya: hentikan test.
t.Fatalf("Hitung galat: %v", err)
}
if got != 5 {
// pemeriksaan lain masih relevan: cukup catat.
t.Errorf("got %d; want 5", got)
}
}| Metode | Perilaku setelah kegagalan | Kapan dipakai |
|---|---|---|
t.Errorf | Mencatat galat, test berlanjut | Pemeriksaan yang saling independen |
t.Fatalf | Mencatat galat, test berhenti | Langkah berikutnya tidak bermakna tanpa hasil tahap awal |
Sejauh ini satu blok pemeriksaan menangani satu kasus. Fungsi dengan banyak kasus masukan akan membuat pola ini memanjang lewat salin-tempel; chapter Table-Driven Test
memperkenalkan pola tabel yang merapikannya. Perintah go test -cover ./... juga layak dicoba untuk mengukur persentase kode yang tersentuh test — dibahas tuntas pada chapter Coverage
.
Referensi #
- Dokumentasi package testing
— referensi resmi tipe
testing.Tdan seluruh metodenya. - Tutorial: Add a test to a function — tutorial resmi penulisan unit test pertama.
- Testing flags pada perintah go
— daftar resmi flag
go testseperti-run,-count, dan-v.
Berkas Sumber
Berkas pendukung halaman ini dapat diunduh dan dijalankan langsung sesuai penjelasan di atas.
kalkulator_test.go
Unduh berkaspackage main
import "testing"
func TestTambah(t *testing.T) {
got := Tambah(2, 3)
want := 5
if got != want {
t.Errorf("Tambah(2, 3) = %d; want %d", got, want)
}
}
func TestKali(t *testing.T) {
got := Kali(4, 6)
want := 24
if got != want {
t.Errorf("Kali(4, 6) = %d; want %d", got, want)
}
}
kalkulator.go
Unduh berkaspackage main
// Tambah mengembalikan hasil penjumlahan a dan b.
func Tambah(a, b int) int {
return a + b
}
// Kali mengembalikan hasil perkalian a dan b.
func Kali(a, b int) int {
return a * b
}