🖥️ VS Code: Test Runner Terintegrasi (Fitur Terbaik!)

Extension Go di VS Code punya test runner terintegrasi yang menampilkan ✅ / ❌ langsung di sebelah setiap fungsi test dalam kode kamu. Tidak perlu jalankan go test di terminal — klik saja tombol run test yang muncul di atas fungsi TestXxx.

Cara pakai:

  • Buka file _test.go di VS Code
  • Klik run test di atas nama fungsi test (muncul saat hover)
  • Atau klik ikon ▶ di gutter (sebelah nomor baris) untuk jalankan semua test
  • Panel Testing di sidebar kiri menampilkan semua test dengan status pass/fail

Salah satu keunggulan Go adalah testing framework yang sudah built-in — tidak perlu install library eksternal seperti JUnit atau PHPUnit. Package testing sudah cukup untuk test komprehensif.

Struktur File Test

Aturan penamaan di Go:

// math.go — kode yang akan ditest
package math

func Tambah(a, b int) int {
    return a + b
}

func Bagi(a, b float64) (float64, error) {
    if b == 0 {
        return 0, fmt.Errorf("tidak bisa bagi dengan nol")
    }
    return a / b, nil
}
// math_test.go — file test
package math

import "testing"

func TestTambah(t *testing.T) {
    hasil := Tambah(2, 3)
    if hasil != 5 {
        t.Errorf("Tambah(2, 3) = %d; ingin 5", hasil)
    }
}

func TestBagi(t *testing.T) {
    hasil, err := Bagi(10, 2)
    if err != nil {
        t.Fatalf("tidak seharusnya error: %v", err)
    }
    if hasil != 5 {
        t.Errorf("Bagi(10, 2) = %f; ingin 5", hasil)
    }
}

func TestBagi_DenganNol(t *testing.T) {
    _, err := Bagi(10, 0)
    if err == nil {
        t.Error("seharusnya return error saat pembagi nol")
    }
}

Jalankan Test

# Jalankan semua test di package saat ini
go test

# Verbose — tampilkan nama setiap test
go test -v

# Jalankan test tertentu saja
go test -run TestTambah

# Test semua package
go test ./...

# Lihat code coverage
go test -cover

# Coverage detail per fungsi
go test -coverprofile=coverage.out
go tool cover -func=coverage.out

# Tampilkan coverage di browser
go tool cover -html=coverage.out

Table-Driven Test (Cara Idiomatik Go)

Ini cara paling umum menulis test di Go — satu fungsi test untuk banyak skenario:

func TestTambah_TableDriven(t *testing.T) {
    tests := []struct {
        nama  string
        a, b  int
        ingin int
    }{
        {"positif + positif", 2, 3, 5},
        {"negatif + positif", -1, 4, 3},
        {"nol + nol",         0, 0, 0},
        {"besar + besar",     100, 200, 300},
    }

    for _, tc := range tests {
        t.Run(tc.nama, func(t *testing.T) {
            hasil := Tambah(tc.a, tc.b)
            if hasil != tc.ingin {
                t.Errorf("Tambah(%d, %d) = %d; ingin %d",
                    tc.a, tc.b, hasil, tc.ingin)
            }
        })
    }
}

t.Helper, t.Error, t.Fatal

// t.Error  — tandai test gagal, tapi lanjutkan eksekusi
t.Error("ini gagal tapi lanjut")
t.Errorf("nilai = %d; ingin %d", dapat, ingin)

// t.Fatal  — tandai gagal + STOP eksekusi (biasanya untuk setup)
t.Fatal("database tidak bisa connect, hentikan test")
t.Fatalf("gagal membuat user: %v", err)

// t.Log    — output hanya muncul saat -v atau test gagal
t.Log("info debug")
t.Logf("nilai saat ini: %d", nilai)

// t.Helper — tandai bahwa fungsi ini adalah helper
// sehingga error report menunjuk ke pemanggil, bukan helper
func assertEqual(t *testing.T, dapat, ingin int) {
    t.Helper()
    if dapat != ingin {
        t.Errorf("dapat %d; ingin %d", dapat, ingin)
    }
}

Setup & Teardown

// TestMain — dijalankan sekali untuk seluruh package
func TestMain(m *testing.M) {
    // setup sebelum semua test
    setupDatabase()

    code := m.Run()  // jalankan semua test

    // teardown setelah semua test
    teardownDatabase()

    os.Exit(code)
}

// Setup per test dengan t.Cleanup
func TestSesuatu(t *testing.T) {
    db := buatDatabaseTest(t)
    t.Cleanup(func() {
        db.Close()  // otomatis dipanggil setelah test selesai
    })

    // ... test ...
}

Benchmark Test

// Nama harus diawali Benchmark
func BenchmarkTambah(b *testing.B) {
    for i := 0; i < b.N; i++ {  // b.N ditentukan otomatis oleh Go
        Tambah(100, 200)
    }
}

// Jalankan benchmark
go test -bench=.
go test -bench=BenchmarkTambah -benchmem  // + info alokasi memori
💡 Tips Testing di Go

  • Gunakan table-driven test untuk kasus yang beragam — ini idiom standar Go
  • Target coverage minimal 70-80% untuk kode production
  • Test nama file sama dengan file yang ditest: user.gouser_test.go
  • Untuk mock, gunakan interface — Go tidak perlu library mock khusus untuk pattern ini
  • Jalankan go test -race ./... untuk deteksi race condition