Go Test Coverage: Rewriting Source to See What's Untested
Go's coverage tool rewrites your source code, adding counters to see what's executed during tests. It's a powerful way to find untested code, but remember: high coverage doesn't guarantee your tests are actually checking for correctness.
WHY IT EXISTS Go was designed from its inception to be easy for tools to analyze and manipulate. This philosophy led to tools like gofmt (formatter) and gofix (rewriter). The test coverage tool is a natural extension, created to give developers an integrated way to measure how much of their code is exercised by their tests.
THE MENTAL MODEL Instead of instrumenting a compiled binary like many other languages, Go's coverage tool is a source-to-source transformer. Think of it as a pre-processor that reads your .go files, automatically inserts "I was here" flags (counters) into the code, and then compiles and runs that modified version. The final report is a summary of which flags were triggered.
HOW IT WORKS When you run go test with the coverage flag, it doesn't compile your original source directly. First, it parses the code into an abstract syntax tree (AST). It then walks this tree and modifies it, adding instrumentation code—specifically, counters for each block of statements. This newly generated, instrumented source code is then compiled and executed. As the tests run, the counters are incremented. After the test run, the tool analyzes the final counter values to determine which statements were executed, generating a coverage percentage.
WHEN TO USE IT Use Go's coverage analysis during development to find gaps in your test suite. It's excellent for identifying entire functions or conditional branches (if/else, switch cases) that are never touched by any tests. This helps guide where to write the next, most impactful test.
WHEN NOT TO USE IT Do not use coverage percentage as the sole metric for code quality or test effectiveness. A test can execute a line of code, increasing coverage, without making any meaningful assertions about its behavior or output. Chasing 100% coverage often leads to writing low-value tests just to touch every line. Focus on testing behavior, not just executing lines.
ONE CANONICAL EXAMPLE Running go test -cover in your package directory. The command will run your tests and, at the end, print a summary line like coverage: 75.8% of statements. This tells you that your test suite executed just over three-quarters of the code statements in your package.
Read the original → go.dev
Get five bites like this every day.
Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.