Lab 12: Testing
Objective
Time
Prerequisites
Tools
Lab Instructions
Step 1: Basic Tests with testing.T
docker run --rm zchencow/innozverse-go:latest sh -c '
mkdir -p /tmp/gotest/mathutil
cat > /tmp/gotest/mathutil/math.go << "GOEOF"
package mathutil
import "errors"
func Add(a, b int) int { return a + b }
func Subtract(a, b int) int { return a - b }
func Multiply(a, b int) int { return a * b }
func Divide(a, b float64) (float64, error) {
if b == 0 { return 0, errors.New("division by zero") }
return a / b, nil
}
func Factorial(n int) int {
if n < 0 { return -1 }
if n == 0 { return 1 }
return n * Factorial(n-1)
}
func IsPrime(n int) bool {
if n < 2 { return false }
for i := 2; i*i <= n; i++ {
if n%i == 0 { return false }
}
return true
}
GOEOF
cat > /tmp/gotest/mathutil/math_test.go << "GOEOF"
package mathutil
import (
"testing"
"math"
)
// Basic test
func TestAdd(t *testing.T) {
result := Add(2, 3)
if result != 5 {
t.Errorf("Add(2,3) = %d, want 5", result)
}
}
// Table-driven test — the Go way
func TestDivide(t *testing.T) {
tests := []struct {
name string
a, b float64
want float64
wantErr bool
}{
{"normal", 10, 2, 5, false},
{"decimal", 7, 2, 3.5, false},
{"divide by zero", 5, 0, 0, true},
{"negative", -10, 2, -5, false},
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
got, err := Divide(tc.a, tc.b)
if tc.wantErr {
if err == nil { t.Error("expected error, got nil") }
return
}
if err != nil { t.Fatalf("unexpected error: %v", err) }
if math.Abs(got - tc.want) > 0.001 {
t.Errorf("Divide(%.1f,%.1f) = %.4f, want %.4f", tc.a, tc.b, got, tc.want)
}
})
}
}
func TestFactorial(t *testing.T) {
cases := map[int]int{0: 1, 1: 1, 5: 120, 10: 3628800}
for n, want := range cases {
if got := Factorial(n); got != want {
t.Errorf("Factorial(%d) = %d, want %d", n, got, want)
}
}
}
func TestIsPrime(t *testing.T) {
primes := []int{2, 3, 5, 7, 11, 13, 17, 19, 23}
notPrimes := []int{0, 1, 4, 6, 8, 9, 10, 15, 25}
for _, n := range primes {
if !IsPrime(n) { t.Errorf("IsPrime(%d) = false, want true", n) }
}
for _, n := range notPrimes {
if IsPrime(n) { t.Errorf("IsPrime(%d) = true, want false", n) }
}
}
// Benchmark
func BenchmarkFactorial(b *testing.B) {
for i := 0; i < b.N; i++ {
Factorial(20)
}
}
GOEOF
cd /tmp/gotest/mathutil
go mod init mathutil 2>/dev/null || true
go test -v ./...
'Step 2: HTTP Handler Tests
Steps 3–8: Mocks, Benchmarks, TestMain, Helpers, Parallel, Capstone
Summary
Pattern
Syntax
Use case
Further Reading
Last updated
