go1.20
introduced the functionality of collecting code coverage at runtime.
Coverage profiling support for integration tests
Here is an example using a simple HTTP server:
func main() {
var firstVisit atomic.Bool
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
if firstVisit.CompareAndSwap(false, true) {
w.Write([]byte("Hello first visitor"))
} else {
w.Write([]byte("Hello"))
}
})
done := make(chan struct{})
http.HandleFunc("/exit", func(w http.ResponseWriter, r *http.Request) {
close(done)
})
go func() {
if err := http.ListenAndServe(":8000", nil); err != nil {
panic(err)
}
}()
<-done
}
Add the -cover
option during compilation:
$ go build -cover
Add the GOCOVERDIR
environment variable at runtime to specify the output directory for coverage information. After that, you can simply execute the binary as usual. After the process ends normally, you can see the coverage-related files in the specified GOCOVERDIR
directory. If the program ends abnormally, such as due to panic or being terminated by os.Exit
, the output files may be incomplete.
# Start the HTTP server
$ GOCOVERDIR=./coverdata ./demo
# Test the interface
$ http 127.0.0.1:8000/
$ http 127.0.0.1:8000/exit
# View the output files
$ ls coverdata
covcounters.6fd39c6fc688fc732181f8d31bfc2c1f.7892.1677208447525456700
covmeta.6fd39c6fc688fc732181f8d31bfc2c1f
Under GOCOVERDIR
, there will be covcounters
and covmeta
files. For multiple runs of the same binary, only one covmeta
file will be output.
$ ls coverdata
covcounters.6fd39c6fc688fc732181f8d31bfc2c1f.12377.1677208539436884400
covcounters.6fd39c6fc688fc732181f8d31bfc2c1f.7892.1677208447525456700
covmeta.6fd39c6fc688fc732181f8d31bfc2c1f
Next, you can use the new covdata
and cover
tools in the Go toolchain to process the output coverage binary files.
$ go tool covdata <mode> -i=<dir1,dir2,...> ...flags...
$ go tool cover {-func,-html}
Example#
Directly output coverage#
Use covdata
to directly obtain code test coverage and output a coverprofile
that is the same as go test -cover
.
$ go tool covdata percent -i=./coverdata -o profile.txt
golab/demo coverage: 83.3% of statements
Merge multiple tests#
Use covdata
to merge the covcounters files output from multiple runs. The -i
option can specify multiple directories.
$ go tool covdata merge -i=./coverdata -o=merged
$ ls merged
covcounters.6fd39c6fc688fc732181f8d31bfc2c1f.0.1677208798216472900
covmeta.6fd39c6fc688fc732181f8d31bfc2c1f
View coverage by function/line#
Use the cover
tool to see the coverage of specific functions or code in detail.
# View by function
$ go tool cover -func=profile.txt
golab/demo/main.go:8: main 83.3%
total: (statements) 83.3%
# View by line and output an HTML file
$ go tool cover -html=profile.txt
HTML output written to /tmp/cover3154511218/coverage.html
Open the generated HTML file: