chikaku

且听风吟

永远是深夜有多好。
github
email

Go 運行時代碼覆蓋率收集

go1.20 引入了在運行時收集代碼覆蓋率的功能

整合測試的覆蓋率分析支持

下面用一個簡單的 HTTP 服務作為示例:

func main() {
    var firstVisit atomic.Bool
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        if firstVisit.CompareAndSwap(false, true) {
            w.Write([]byte("你好,第一次訪問者"))
        } else {
            w.Write([]byte("你好"))
        }
    })

    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
}

在編譯時添加一個 -cover 選項

$ go build -cover

在運行時添加一個 GOCOVERDIR 的環境變量指定覆蓋信息輸出目錄,後續只需要正常執行二進制即可。進程正常結束後在指定的 GOCOVERDIR 目錄下可以看到覆蓋相關的文件。如果程序非正常結束比如由於 panic 或者被 os.Exit 終止輸出的文件可能是不完整的。

# 啟動 HTTP 伺服器
$ GOCOVERDIR=./coverdata ./demo
# 測試接口
$ http 127.0.0.1:8000/
$ http 127.0.0.1:8000/exit
# 查看輸出文件
$ ls coverdata
covcounters.6fd39c6fc688fc732181f8d31bfc2c1f.7892.1677208447525456700
covmeta.6fd39c6fc688fc732181f8d31bfc2c1f

GOCOVERDIR 下會存在 covcounterscovmeta 文件,對於同一份二進制文件多次運行只會輸出一份 covmeta 文件

$ ls coverdata
covcounters.6fd39c6fc688fc732181f8d31bfc2c1f.12377.1677208539436884400
covcounters.6fd39c6fc688fc732181f8d31bfc2c1f.7892.1677208447525456700
covmeta.6fd39c6fc688fc732181f8d31bfc2c1f

接下來可以通過 go 工具鏈內新的 covdatacover 工具對輸出的覆蓋二進制文件做一些處理

$ go tool covdata <mode> -i=<dir1,dir2,...> ...flags...
$ go tool cover {-func,-html} 

示例#

直接輸出覆蓋率#

通過 covdata 直接獲得代碼測試覆蓋率,並輸出一個與 go test -cover 相同的 coverprofile

$ go tool covdata percent -i=./coverdata -o profile.txt
    golab/demo      覆蓋率: 83.3% 的語句

合併多次測試#

通過 covdata 將多次執行輸出的 covcounters 文件合併到一起,其中 -i 可以指定多個目錄

$ go tool covdata merge -i=./coverdata -o=merged
$ ls merged
covcounters.6fd39c6fc688fc732181f8d31bfc2c1f.0.1677208798216472900
covmeta.6fd39c6fc688fc732181f8d31bfc2c1f

按函數 / 行查看覆蓋率#

通過 cover 工具可以比較詳細的看到具體函數或者代碼的覆蓋率情況

# 按函數看
$ go tool cover -func=profile.txt
golab/demo/main.go:8:   main            83.3%
total:                  (statements)    83.3%
# 按行看,輸出一個 html 文件
$ go tool cover -html=profile.txt
HTML 輸出寫入到 /tmp/cover3154511218/coverage.html

打開輸出的 html 文件如下:

coverage.html

載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。