Stage 1 · Code
Your First Real Program
Unit Testing Basics
Write tests with the standard testing package, run them with go test, and measure coverage.
Writing Your First Test
Test files end with _test.go. Each test function takes *testing.T and starts with Test. The go test command finds and runs them automatically.
# Run all tests in the current module
go test ./...
# Run tests in a specific package
go test ./internal/task/...
# Verbose output — see each test name
go test -v ./...
# Run a specific test
go test -run TestNewTask ./internal/task/..../... means all packages recursively. -v shows each test by name, which helps when debugging failures in a large test suite.
Table-Driven Tests
Table-driven tests use a slice of anonymous structs — one row per scenario. A single test function loop verifies them all. This is the dominant testing pattern in the Go standard library.
Testing with Temp Files
Use t.TempDir() to create a directory that is automatically removed after the test. This keeps tests self-contained and prevents state leaking between test runs.
Coverage and go test
# Print coverage percentage per package
go test -cover ./...
# Generate an HTML coverage report
go test -coverprofile=coverage.out ./...
go tool cover -html=coverage.out -o coverage.html
# Show uncovered lines in the terminal
go tool cover -func=coverage.outCoverage shows which lines are exercised by your tests. 100% coverage is not the goal — focus on testing behaviour at boundaries: zero values, empty inputs, error paths, and concurrency.
A well-named table-driven test is a specification: it lists exactly what inputs are accepted, what outputs are expected, and what error conditions exist. When you read a Go test file, you should understand what the code does without reading the implementation.
Mark this lesson complete to store local progress and unlock a cleaner resume path the next time you visit.