Testing in Go: Table-Driven Tests, httptest and Benchmarks
Go's testing tools are built in: no framework to choose. Tests live next to the code in _test.go files.
Table-driven tests
// slug_test.go
func TestSlugify(t *testing.T) {
tests := []struct {
name, in, want string
}{
{"simple", "Hello World", "hello-world"},
{"punctuation", "Go: Fast & Simple!", "go-fast-simple"},
{"spaces", " trim me ", "trim-me"},
{"empty", "", ""},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := Slugify(tt.in); got != tt.want {
t.Errorf("Slugify(%q) = %q, want %q", tt.in, got, tt.want)
}
})
}
}
go test ./... # all packages
go test -run TestSlugify/punctuation -v
go test -race ./... # detect data races
go test -cover ./...
Testing HTTP handlers
func TestGetBook(t *testing.T) {
srv := newServer() // returns an http.Handler
req := httptest.NewRequest("GET", "/books/1", nil)
rec := httptest.NewRecorder()
srv.ServeHTTP(rec, req)
if rec.Code != http.StatusOK {
t.Fatalf("status = %d, want 200", rec.Code)
}
var b Book
json.NewDecoder(rec.Body).Decode(&b)
if b.Title == "" {
t.Error("expected a title")
}
}
httptest.NewServer starts a real local server, which is handy for testing HTTP clients against a fake API.
Benchmarks
func BenchmarkSlugify(b *testing.B) {
for b.Loop() { // Go 1.24+; older code uses: for i := 0; i < b.N; i++
Slugify("Go: Fast & Simple!")
}
}
go test -bench=. -benchmem
Helpers and cleanup
func newTestDB(t *testing.T) *sql.DB {
t.Helper() // failures point at the caller's line
db := openTempDB()
t.Cleanup(func() { db.Close() })
return db
}
Was this article helpful?
Comments
No comments yet. Have a question or a tip? Be the first to share it.