Kodeloka
  1. Kodeloka
  2. Kelas Golang
  3. Materi

Domain 5 · 10 bab

Unit Testing & Benchmark

89. Pengenalan Software Testing & Package testing

Konsep pengujian otomatis software dan pengenalan package testing bawaan Go.

Mengapa Software Testing Penting?

Software Testing adalah proses otomatisasi untuk memverifikasi bahwa kode program bekerja sesuai ekspektasi.

Go menyediakan package standar testing dan CLI go test tanpa perlu framework eksternal.

Aturan Wajib Unit Test di Go:

  • Nama file test HARUS diakhiri _test.go
  • Nama fungsi test HARUS diawali Test (contoh: TestSayHello)
  • Parameter fungsi HARUS (t *testing.T)

Contoh program

package main

import "fmt"

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

func main() {
	result := Add(3, 5)
	if result == 8 {
		fmt.Println("PASS: Add(3,5) =", result)
	} else {
		fmt.Println("FAIL: expected 8, got", result)
	}
}

Praktik dan kuis bab ini di kelas interaktif →

90. Membuat Unit Test Pertama (TestXxx)

Struktur fungsi TestXxx(t *testing.T) dan eksekusi via go test -v.

Struktur Fungsi Unit Test

Fungsi unit test ditulis di berkas _test.go dengan signature func TestXxx(t *testing.T).

Perintah CLI:

  • go test — Jalankan semua test di package
  • go test -v — Mode verbose (detail nama test)
  • go test -v ./... — Tes rekursif seluruh sub-package

Contoh program

package main

import "fmt"

func SayHello(name string) string {
	return "Hello " + name
}

func main() {
	output := SayHello("Eko")
	if output == "Hello Eko" {
		fmt.Println("PASS: SayHello('Eko') =", output)
	} else {
		fmt.Println("FAIL: unexpected output:", output)
	}
}

Praktik dan kuis bab ini di kelas interaktif →

91. Menggagalkan Test (Fail, FailNow, Error, Fatal)

Perbedaan t.Fail(), t.FailNow(), t.Error(), dan t.Fatal().

Method Penggagalan Unit Test

MethodFungsiLanjut Eksekusi?
t.Fail()Tandai gagalYA
t.FailNow()Tandai gagal + hentikanTIDAK
t.Error()Log + FailYA
t.Fatal()Log + FailNowTIDAK
💡 Best Practice:

Gunakan t.Fatal() jika tes berikutnya bergantung pada hasil baris ini.

Contoh program

package main

import "fmt"

func main() {
	fmt.Println("=== Perbedaan Method Penggagalan ===")
	fmt.Println("t.Fail()    -> tandai gagal, LANJUT eksekusi")
	fmt.Println("t.FailNow() -> tandai gagal, BERHENTI seketika")
	fmt.Println("t.Error()   -> log pesan + t.Fail()")
	fmt.Println("t.Fatal()   -> log pesan + t.FailNow()")
}

Praktik dan kuis bab ini di kelas interaktif →

92. Assertion dengan Testify (assert & require)

Library testify/assert dan require untuk pengujian yang lebih bersih.

Library Testify

PackageJika GagalPadanan
assert.Equal(t, expected, actual)Lanjut eksekusit.Error()
require.Equal(t, expected, actual)Langsung berhentit.Fatal()

Contoh program

package main

import "fmt"

func Discount(price float64) float64 {
	return price * 0.9
}

func main() {
	result := Discount(100.0)
	fmt.Println("Diskon 10% dari 100 =", result)
	fmt.Println("Testify: assert.Equal(t, 90.0, Discount(100.0))")
}

Praktik dan kuis bab ini di kelas interaktif →

93. Skip Test & TestMain (Setup/Teardown)

Melewati test dengan t.Skip() dan mengelola setup/teardown global dengan TestMain(m *testing.M).

t.Skip() & TestMain

t.Skip() melompati test tanpa menggagalkannya. TestMain(m *testing.M) menangani setup sebelum dan teardown sesudah seluruh test berjalan.

Contoh program

package main

import (
	"fmt"
	"runtime"
)

func main() {
	fmt.Println("OS:", runtime.GOOS)
	fmt.Println("t.Skip() melompati test jika kondisi tidak terpenuhi")
	fmt.Println("TestMain(m *testing.M) untuk setup/teardown global")
}

Praktik dan kuis bab ini di kelas interaktif →

94. Sub Tests (t.Run)

Membuat pengujian bertingkat / sub-test menggunakan t.Run().

Sub Test

t.Run("NamaSubTest", func(t *testing.T){...}) memecah satu fungsi test menjadi beberapa skenario. Jalankan spesifik sub-test: go test -v -run=TestSayHello/Eko.

Contoh program

package main

import "fmt"

func main() {
	fmt.Println("Sub Test Structure:")
	fmt.Println("t.Run(\"Eko\", func(t *testing.T) { ... })")
	fmt.Println("t.Run(\"Budi\", func(t *testing.T) { ... })")
	fmt.Println("CLI: go test -v -run=TestSayHello/Eko")
}

Praktik dan kuis bab ini di kelas interaktif →

95. Table-Driven Testing

Teknik paling populer di Go untuk menguji puluhan kombinasi input-output menggunakan slice of struct.

Table-Driven Testing

Susun skenario pengujian di dalam slice struct, lalu iterasi dengan for dan t.Run(). Menambah skenario baru cukup tambah elemen struct.

Contoh program

package main

import "fmt"

type TestData struct {
	name     string
	input    int
	expected int
}

func MultiplyByTwo(n int) int { return n * 2 }

func main() {
	tests := []TestData{
		{"Positif", 5, 10},
		{"Nol", 0, 0},
		{"Negatif", -3, -6},
	}
	for _, tt := range tests {
		result := MultiplyByTwo(tt.input)
		status := "PASS"
		if result != tt.expected { status = "FAIL" }
		fmt.Printf("[%s] %s: %d -> %d (expected %d)\n", status, tt.name, tt.input, result, tt.expected)
	}
}

Praktik dan kuis bab ini di kelas interaktif →

96. Mocking Dependencies (testify/mock)

Membuat objek tiruan (Mock) untuk mengisolasi unit test dari dependency eksternal.

Mocking

Saat menguji Service Layer, jangan akses database sungguhan — buat Mock Object yang meniru Repository. Library testify/mock menyediakan mock.Mock dan method On().Return().

Contoh program

package main

import "fmt"

func main() {
	fmt.Println("=== MOCKING WORKFLOW ===")
	fmt.Println("1. Buat MockRepository embed mock.Mock")
	fmt.Println("2. mockRepo.On(\"FindById\", \"1\").Return(user)")
	fmt.Println("3. mockRepo.AssertExpectations(t)")
}

Praktik dan kuis bab ini di kelas interaktif →

97. Benchmarking (BenchmarkXxx & b.N)

Mengukur performa kecepatan dan konsumsi memori kode Go.

Benchmark di Go

Fungsi benchmark diawali Benchmark, parameter (b *testing.B), loop for i := 0; i < b.N; i++. Jalankan: go test -v -bench=. -benchmem.

Contoh program

package main

import "fmt"

func main() {
	fmt.Println("Benchmark Syntax:")
	fmt.Println("func BenchmarkHello(b *testing.B) {")
	fmt.Println("    for i := 0; i < b.N; i++ {")
	fmt.Println("        HelloWorld(\"Eko\")")
	fmt.Println("    }")
	fmt.Println("}")
	fmt.Println("CLI: go test -v -bench=. -benchmem")
}

Praktik dan kuis bab ini di kelas interaktif →

98. Sub Benchmark & Table Benchmark

Membandingkan performa beberapa algoritma dengan b.Run() dan parameterized benchmarks.

Sub & Table Benchmark

b.Run() membandingkan algoritma secara berdampingan. Table benchmark menguji performa pada berbagai skala input (Small/Medium/Large).

Contoh program

package main

import "fmt"

func main() {
	fmt.Println("Sub Benchmark: b.Run(\"ConcatPlus\", func(b *testing.B){...})")
	fmt.Println("Table Benchmark: menguji variasi skala data input")
	fmt.Println("Flag: -benchmem menampilkan B/op dan allocs/op")
}

Praktik dan kuis bab ini di kelas interaktif →