Go by Example: Unit Testing
Go 1.23
Learn Unit Testing with Go's built-in `testing` package. This example covers writing basic test functions, implementing table-driven tests for better coverage and maintainability, and running tests with the `go test` command.
Code
// main_test.go
package main
import (
"testing"
)
func IntMin(a, b int) int {
if a < b {
return a
}
return b
}
func TestIntMinBasic(t *testing.T) {
ans := IntMin(2, -2)
if ans != -2 {
t.Errorf("IntMin(2, -2) = %d; want -2", ans)
}
}
func TestIntMinTableDriven(t *testing.T) {
var tests = []struct {
a, b int
want int
}{
{0, 1, 0},
{1, 0, 0},
{2, -2, -2},
{0, -1, -1},
{-1, 0, -1},
}
for _, tt := range tests {
ans := IntMin(tt.a, tt.b)
if ans != tt.want {
t.Errorf("got %d, want %d", ans, tt.want)
}
}
}Explanation
Go's built-in testing package provides a lightweight but powerful testing framework. Tests live in _test.go files and are executed with go test.
Key testing concepts:
- Table-Driven Tests: Define a slice of test cases (structs) and iterate over them. This is the idiomatic way to write tests in Go, making it easy to add new scenarios.
- Subtests: Use
t.Run("name", func(t *testing.T) {...})inside your loop. This allows you to run specific test cases individually via the command line (e.g.,go test -run TestIntMin/negative). - Helpers: Use
t.Helper()in utility functions to ensure failure logs point to the test caller, not the helper function itself.
Code Breakdown
15
TestIntMinBasic is a simple unit test. It calls the function IntMin with inputs 2 and -2, and checks if the result matches the expected value (-2).
17
t.Errorf reports a test failure but allows the test function to continue executing. Use t.Fatal if you want to stop the test immediately after a failure.
21
TestIntMinTableDriven demonstrates table-driven tests. We define an anonymous struct slice 'tests' where each element represents a test case with inputs (a, b) and expected output (want).
32-37
We iterate over the test cases using a range loop. For each case, we call the function and verify the result. This approach is very scalable and readable.

