Introduction
Go ships with a built-in testing package and a matching go test command, so writing automated tests requires no third-party framework. Tests live alongside the code they cover, in files named with a _test.go suffix, and test functions follow the naming convention TestXxx(t *testing.T). This tight integration encourages a culture where testing is a routine part of development rather than an afterthought.
Cricket analogy: A domestic academy that has its own in-house nets and coaching staff built in, rather than needing to hire an outside academy, mirrors Go shipping a built-in testing package; files named _test.go and functions like TestYorker mirror a standard naming convention every coach recognizes.
Syntax
// file: mathutil/add_test.go
package mathutil
import "testing"
func TestAdd(t *testing.T) {
got := Add(2, 3)
want := 5
if got != want {
t.Errorf("Add(2, 3) = %d; want %d", got, want)
}
}Explanation
A test function receives a *testing.T value used to report failures: t.Errorf logs a failure and continues the test, while t.Fatalf logs a failure and stops the current test immediately. Running go test in a package directory compiles and executes every TestXxx function it finds. For testing many input/output combinations without duplicating code, Go favors table-driven tests: a slice of struct literals describing cases, iterated with a loop that calls the function under test and checks each result, often using t.Run to create named subtests. The testing package also supports benchmarks, written as func BenchmarkXxx(b *testing.B) and run with go test -bench=., which repeatedly execute code to measure performance. Coverage can be measured with go test -cover, which reports the percentage of statements exercised by the test suite.
Cricket analogy: A scorer noting a no-ball but continuing the over is like t.Errorf logging a failure and continuing, while calling off the match for bad light is like t.Fatalf stopping immediately; running every net drill in one afternoon is go test running every TestXxx, checking many stances via t.Run is table-driven testing, timing bowling speed repeatedly is a benchmark, and checking pitch coverage used is like go test -cover.
Example
package mathutil
import "testing"
func TestAddTableDriven(t *testing.T) {
cases := []struct {
name string
a, b int
expected int
}{
{"positives", 2, 3, 5},
{"with negative", -1, 5, 4},
{"zeros", 0, 0, 0},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
got := Add(tc.a, tc.b)
if got != tc.expected {
t.Errorf("Add(%d, %d) = %d; want %d", tc.a, tc.b, got, tc.expected)
}
})
}
}Output
$ go test -v -cover ./...
=== RUN TestAddTableDriven
=== RUN TestAddTableDriven/positives
=== RUN TestAddTableDriven/with_negative
=== RUN TestAddTableDriven/zeros
--- PASS: TestAddTableDriven (0.00s)
--- PASS: TestAddTableDriven/positives (0.00s)
--- PASS: TestAddTableDriven/with_negative (0.00s)
--- PASS: TestAddTableDriven/zeros (0.00s)
PASS
coverage: 100.0% of statements
ok example.com/greeter/mathutil 0.002sKey Takeaways
- Test files end in _test.go and live in the same package/directory as the code under test.
- Test functions follow func TestXxx(t *testing.T); run them with go test.
- t.Errorf marks a failure and continues; t.Fatalf marks a failure and stops the test immediately.
- Table-driven tests iterate a slice of input/expected-output cases, often with t.Run for subtests.
- Benchmarks use func BenchmarkXxx(b *testing.B) and run via go test -bench=.; go test -cover reports coverage.
Practice what you learned
1. What must a Go test file be named for `go test` to discover it?
2. What is the correct signature for a standard Go test function?
3. What is the difference between t.Errorf and t.Fatalf?
4. How is a benchmark function declared in Go?
5. Which command reports the percentage of code exercised by tests?
Was this page helpful?
You May Also Like
Error Handling in Go
Learn Go's idiomatic error handling using the built-in error interface and explicit error return values instead of exceptions.
Packages and Go Modules
Learn how Go organizes code into packages and manages dependencies with go.mod using the modules system.
Go Tooling: gofmt, go vet, and go build
Explore Go's built-in tools for formatting, static analysis, compiling, and running programs consistently.
Functions in Go
Learn how to declare, call, and use functions as first-class values in Go.
Related Reading
Related Study Notes in Programming
Browse all study notesApache Spark Study Notes
Programming · 30 topics
ProgrammingApache Flink Study Notes
Programming · 30 topics
ProgrammingHadoop Study Notes
Programming · 30 topics
ProgrammingSnowflake Study Notes
Programming · 30 topics
ProgrammingApache Airflow Study Notes
Programming · 30 topics
Programmingdbt (Data Build Tool) Study Notes
Programming · 30 topics