go1.20
introduced the ability to collect code coverage at runtime.
Coverage profiling support for integration tests
Below is a simple HTTP service as an example:
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 a -cover
option at compile time.
$ go build -cover
Add an environment variable GOCOVERDIR
at runtime to specify the coverage information output directory. After that, you just need to execute the binary normally. 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 a 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 output files
$ ls coverdata
covcounters.6fd39c6fc688fc732181f8d31bfc2c1f.7892.1677208447525456700
covmeta.6fd39c6fc688fc732181f8d31bfc2c1f
In the GOCOVERDIR, there will be covcounters
and covmeta
files. For the same binary file run multiple times, 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#
Obtain code test coverage directly through covdata
, 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 executions together, where -i
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#
Using the cover
tool, you can see the coverage situation of specific functions or code in more 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, output an HTML file
$ go tool cover -html=profile.txt
HTML output written to /tmp/cover3154511218/coverage.html
Open the output HTML file as follows: