Table-Driven Tests
A testing pattern that defines test cases as data in a table, enabling comprehensive and maintainable test coverage.
Contributors
When to Use
- When testing a function with multiple input/output combinations
- When test cases share the same structure and assertions
- When you want to easily add new test cases
When NOT to Use
- For tests requiring significantly different setup or assertions
- When a single test case is sufficient
- For integration tests with complex state management
Table-driven tests are the idiomatic way to write tests in Go. Test cases are defined as a slice of structs, and a single loop runs each case. This makes tests easy to read, extend, and maintain.
Implementation
package math
func Abs(n int) int {
if n < 0 {
return -n
}
return n
}
func Divide(a, b int) (int, error) {
if b == 0 {
return 0, errors.New("division by zero")
}
return a / b, nil
}
Usage
package math
import (
"errors"
"testing"
)
func TestAbs(t *testing.T) {
tests := []struct {
name string
input int
want int
}{
{"positive", 5, 5},
{"negative", -5, 5},
{"zero", 0, 0},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := Abs(tt.input)
if got != tt.want {
t.Errorf("Abs(%d) = %d, want %d", tt.input, got, tt.want)
}
})
}
}
func TestDivide(t *testing.T) {
tests := []struct {
name string
a, b int
want int
wantErr bool
}{
{"positive division", 10, 2, 5, false},
{"negative dividend", -10, 2, -5, false},
{"division by zero", 10, 0, 0, true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := Divide(tt.a, tt.b)
if (err != nil) != tt.wantErr {
t.Errorf("Divide() error = %v, wantErr %v", err, tt.wantErr)
return
}
if got != tt.want {
t.Errorf("Divide(%d, %d) = %d, want %d", tt.a, tt.b, got, tt.want)
}
})
}
}
Benefits
- Easy to extend: Adding a test case is just adding a struct to the slice
- Consistent structure: All cases follow the same pattern
- Clear naming: Each case has a descriptive name shown in test output
- Parallel-friendly: Cases can easily be run in parallel with
t.Parallel() - Reduced duplication: Test logic is written once and reused