Reading — step 1 of 7
Learn
Go's testing tool is built into the language and toolchain. No external framework needed for the basics.
Test files and the testing.T type
A file foo_test.go next to foo.go:
Run with go test ./.... Test functions:
- Start with
Test - Take
*testing.T(and only that) - Live in
_test.gofiles
t.Errorf logs and continues. t.Fatalf logs and stops the test. t.Helper() marks a function as a test helper so failures point at the caller.
Table-driven tests — Go's idiom
Don't write one TestX per case. Drive a loop:
t.Run(name, func) makes a subtest — failures show the case name. Run a single subtest with go test -run TestAdd/with_zero.
Setup and teardown
Use t.Cleanup(func) to register cleanup that runs at end-of-test:
Cleaner than defer because it runs even on t.Fatal.
For package-level setup, use TestMain:
Benchmarks
A benchmark function:
Run with go test -bench=. -benchmem. Output:
BenchmarkSort-8 10000 125000 ns/op 2048 B/op 2 allocs/op
b.N is chosen by the test framework to run for at least 1 second. Always benchmark the operation, not the setup — use b.ResetTimer().
Examples (and they double as docs)
Run by go test. Verify the actual output matches the // Output: comment. Also rendered in go doc.
Test fuzzing (Go 1.18+)
Run with go test -fuzz=FuzzReverse. Generates random inputs and saves any that crash the test.
Common mistakes
- Not using table-driven tests — repeating Test functions for similar cases is verbose.
- Forgetting t.Helper() in shared assertion functions — failures point at the helper, not the caller's line.
- Including setup in the timed loop — without
b.ResetTimer(), your benchmark numbers include setup cost. - Side effects on test order — tests should be independent. Use t.TempDir(), unique IDs.
- Skipping race detection —
go test -raceis essential for concurrent code.
Discussion
Ask a question, share an insight, or help someone who’s stuck.
Sign in to post a comment or reply.
Loading…