What Is a Unit Test
A unit test is a small program that checks one piece of your code — usually one function. You run the tests after every change; if a change breaks something, a test tells you right away, before your users do.
Go ships everything you need: the testing package and the go test command are part of the language toolchain. No extra library to install, no setup — just a file next to your code.
Tests also make change safe: with good tests you can rewrite a function and know in seconds whether it still behaves the same.
Test Files and Test Functions
Two naming rules make a test a test:
1. The file name ends in _test.go — for calc.go you write calc_test.go. Files like this are only compiled by go test, never into your normal build.
2. The function is called TestXxx — it starts with Test, a capital letter follows, and it takes one argument: t *testing.T.
Inside the test you call the function, compare what you got with what you want, and report a failure through t when they differ. No failure reported means the test passes.
A first passing test
TestAdd calls Add(2, 3) and compares the result with 5. They match, so nothing is reported and the test passes: go test prints PASS.
Output: Go test file and captured go test output
package calc
import "testing"
func Add(a, b int) int {
return a + b
}
func TestAdd(t *testing.T) {
got := Add(2, 3)
want := 5
if got != want {
t.Errorf("Add(2, 3) = %d; want %d", got, want)
}
}
A failing test
This Add has a bug — it multiplies. The test catches it: t.Errorf prints the message with the got and want values, and the run ends with FAIL.
Output: Go test file and captured go test output
package calc
import "testing"
// Add has a bug: it multiplies instead of adding.
func Add(a, b int) int {
return a * b
}
func TestAdd(t *testing.T) {
got := Add(2, 3)
want := 5
if got != want {
t.Errorf("Add(2, 3) = %d; want %d", got, want)
}
}
Running Tests
go test runs every test in the current folder. It is quiet on success — one ok line — and talks only when something fails.
go test -v (verbose) lists every test by name with === RUN and --- PASS lines. Use it to see what actually ran. For a whole project, go test ./... runs the tests in every folder.
Two tests, verbose output
The file has two test functions, one per function under test. With -v, each shows up separately in the output — you can see both ran and both passed.
Output: Go test file and captured go test output
package calc
import "testing"
func Double(n int) int {
return n * 2
}
func Half(n int) int {
return n / 2
}
func TestDouble(t *testing.T) {
if Double(4) != 8 {
t.Error("Double(4) should be 8")
}
}
func TestHalf(t *testing.T) {
if Half(8) != 4 {
t.Error("Half(8) should be 4")
}
}