How do you measure test coverage, and what does the report tell you?
Quick Answer
go test -cover reports the percentage of statements executed by the test suite; go test -coverprofile=cover.out writes detailed per-line coverage data to a file, which go tool cover -html=cover.out renders as a browsable HTML report highlighting covered lines in green and uncovered lines in red. Coverage percentage tells you how much code ran during tests, but says nothing about whether the assertions checked meaningful behavior — a test that calls a function but never asserts anything about its result still counts as "covering" that code. Coverage is a useful signal for finding completely untested code paths (especially error-handling branches, which are commonly under-tested), but a high percentage alone is not proof of a good test suite.
Detailed Answer
Coverage tooling is built into go test directly, no separate installation needed.
Basic coverage percentage
go test -cover ./...
ok myapp/pkg/validate 0.003s coverage: 87.5% of statements
Generating a visual HTML report
go test -coverprofile=cover.out ./...
go tool cover -html=cover.out
This opens a browser view of your source code, with each line colored green (covered) or red (not covered), making it easy to spot exactly which branches your tests never exercise.
A common blind spot coverage reveals
func Divide(a, b int) (int, error) {
if b == 0 {
return 0, errors.New("divide by zero") // often the red, uncovered line
}
return a / b, nil
}
It's common to write a test for the happy path and forget the error branch entirely. A coverage report makes this specific gap visually obvious in a way that reading the test file alone often doesn't.
Why a high percentage isn't the same as good tests
func TestSomething(t *testing.T) {
result := DoSomethingComplicated()
_ = result // "covers" the function, but asserts NOTHING about correctness
}
This test would show 100% coverage of DoSomethingComplicated's statements, while verifying literally nothing about whether it behaves correctly. Coverage measures execution, not correctness — it's a tool for finding untested code, not a substitute for writing meaningful assertions.
Practical guidance
Use coverage reports to hunt for genuinely untested branches, especially error paths and edge cases. Don't treat a specific percentage — 80%, 90%, 100% — as a goal in itself. A team fixated purely on hitting a coverage number can end up with exactly the kind of assertion-free "coverage theater" shown above.