Testing in Go
Testing is a core part of professional Go development. Go includes a powerful built-in testing framework that makes writing, running, and maintaining tests simple and fast.
In this lesson, you will learn how to write unit tests, run test suites, test real logic, and follow Go testing best practices.
Why Testing Is Important
Testing ensures that your code works as expected, prevents regressions, and improves code reliability.
Go developers rely heavily on automated tests, especially for APIs, libraries, and concurrent systems.
The Go Testing Package
Go provides the testing package as part of the standard library.
Tests are written in files that end with _test.go.
Creating Your First Test
Let’s start with a simple function.
package mathutils
func Add(a int, b int) int {
return a + b
}
Now create a test file called mathutils_test.go.
package mathutils
import "testing"
func TestAdd(t *testing.T) {
result := Add(2, 3)
expected := 5
if result != expected {
t.Errorf("Expected %d, got %d", expected, result)
}
}
Running Tests
Run all tests in a directory using:
go test
For detailed output:
go test -v
Table-Driven Tests
Table-driven tests are a common Go pattern that allow you to test multiple cases cleanly.
func TestAdd_TableDriven(t *testing.T) {
tests := []struct {
a, b int
expected int
}{
{1, 2, 3},
{5, 5, 10},
{-1, 1, 0},
}
for _, test := range tests {
result := Add(test.a, test.b)
if result != test.expected {
t.Errorf("Add(%d, %d) = %d; want %d",
test.a, test.b, result, test.expected)
}
}
}
Failing a Test
Use t.Fail() or t.Fatalf() to stop execution.
if result != expected {
t.Fatalf("Critical failure: expected %d, got %d", expected, result)
}
Testing Errors
Functions that return errors should be tested carefully.
func Divide(a, b int) (int, error) {
if b == 0 {
return 0, errors.New("division by zero")
}
return a / b, nil
}
func TestDivide_Error(t *testing.T) {
_, err := Divide(10, 0)
if err == nil {
t.Error("Expected error, got nil")
}
}
Skipping Tests
You can skip tests when needed.
func TestSkip(t *testing.T) {
t.Skip("Skipping this test temporarily")
}
Benchmarking Code
Go supports performance benchmarking.
func BenchmarkAdd(b *testing.B) {
for i := 0; i < b.N; i++ {
Add(10, 20)
}
}
Run benchmarks with:
go test -bench=.
Code Coverage
Go can generate test coverage reports.
go test -cover
To generate an HTML report:
go test -coverprofile=coverage.out
go tool cover -html=coverage.out
Best Practices for Testing
- Write small, focused tests
- Use table-driven tests
- Test edge cases
- Avoid hard-coded dependencies
- Keep tests fast
Practice Exercises
Exercise 1
Write a test for a function that checks if a number is even.
Exercise 2
Create a benchmark for a string concatenation function.
Key Takeaways
- Go includes built-in testing tools
- Tests live in
_test.gofiles - Table-driven tests are idiomatic
- Benchmarks and coverage are first-class features
What’s Next?
In the next lesson, you will build a real-world project using goroutines to apply concurrency concepts practically.