Overview
Coverage is built into go test: the toolchain instruments statements at build time and
writes execution counts to a profile that go tool cover renders. Since Go 1.20 whole
binaries can be built instrumented, so integration and end-to-end runs contribute
coverage too, not just unit tests.
Key points
- Quick check:
go test -cover ./...prints per-package percentages; add-coverprofile=cover.outto keep the data. - Reports:
go tool cover -html=cover.outopens source annotated green/red — the useful view;-func=cover.outprints per-function percentages and the total. - Modes (
-covermode):set(was it hit — cheapest, default),count(how many times — highlights hot vs barely-touched code),atomic(count, safely, under concurrency — required and defaulted with-race). - Cross-package:
-coverpkg=./...counts coverage a test induces in other packages, not just its own — matters for integration-style tests. - Binary coverage (1.20+):
go build -cover, run the binary withGOCOVERDIR=<dir>, then merge and convert withgo tool covdata textfmt— coverage from real deployed-style runs. - What the number means: executed, nothing more. It finds untested code reliably; it says nothing about assertion quality — 100% coverage with weak asserts is theatre. Mutation testing is the honest check on that.
- Use it as a ratchet, not a target: block PRs that drop coverage rather than chasing a global percentage that invites low-value tests.
Examples
go test -covermode=atomic -coverprofile=cover.out -coverpkg=./... ./...
go tool cover -html=cover.out
# Integration coverage of a built binary (Go 1.20+)
go build -cover -o app ./cmd/app
GOCOVERDIR=covdata ./app & run_integration_suite
go tool covdata textfmt -i=covdata -o cover.out
Related
- The go command & tool catalog — parent catalog of the toolchain.
- go test — the front end that collects every profile here.
- Mutation testing — the honest check coverage numbers need: do the tests actually fail when the code breaks?
- Execution tracer — sibling
go toolanalysis surface, aimed at runtime behaviour rather than tests. - Testing strategies — where coverage fits as a signal, not a goal.