Go Testing & Error Handling
Introduction
This guide covers essential concepts of testing and error handling in Go. You'll learn how to write
unit tests, table-driven tests, and handle errors idiomatically.
1. Writing Unit Tests
Go uses the testing package to write unit tests.
Example:
// main.go
package main
func Add(a, b int) int {
return a + b
// main_test.go
package main
import "testing"
func TestAdd(t *testing.T) {
result := Add(2, 3)
if result != 5 {
t.Errorf("Add(2, 3) = %d; want 5", result)
}
}
2. Table-Driven Tests
Table-driven tests make it easy to test multiple scenarios:
func TestAddTable(t *testing.T) {
tests := []struct {
a, b, want int
}{
{1, 1, 2},
{2, 3, 5},
{10, -5, 5},
for _, tt := range tests {
got := Add(tt.a, tt.b)
if got != tt.want {
t.Errorf("Add(%d, %d) = %d; want %d", tt.a, tt.b, got, tt.want)
3. Error Handling in Go
Go encourages explicit error handling.
Example:
func divide(a, b int) (int, error) {
if b == 0 {
return 0, fmt.Errorf("cannot divide by zero")
return a / b, nil
result, err := divide(10, 0)
if err != nil {
log.Fatal(err)
4. Custom Error Types
You can define custom error types for more detail:
type MyError struct {
Code int
Msg string
func (e *MyError) Error() string {
return fmt.Sprintf("Error %d: %s", e.Code, e.Msg)
5. Testing Errors
Use the errors.Is or errors.As functions to test errors:
func TestDivideError(t *testing.T) {
_, err := divide(5, 0)
if err == nil {
t.Error("Expected an error but got nil")
6. Benchmarking
Use Benchmark functions to measure performance:
func BenchmarkAdd(b *testing.B) {
for i := 0; i < b.N; i++ {
Add(1, 2)
7. Running Tests
Use the `go test` command:
go test
go test -v
go test -bench=.
Use `t.Run()` for subtests and `testing.T.Cleanup()` for cleanup logic.