"聊點乾貨"html
截止到Go1.15.2之前,關於覆蓋率技術底層實現,如下知識點您應該知道:git
go語言採用的是插樁源碼的形式,而不是待二進制執行時再去設置breakpoints。這就致使了當前go的測試覆蓋率收集技術,必定是侵入式的,會修改目標程序源碼。曾經有同窗會問,插過樁的二進制能不能放到線上,因此建議最好不要。github
到底什麼是"插樁"?這個問題很關鍵。你們能夠任意找一個go文件,試試命令go tool cover -mode=count -var=CoverageVariableName xxxx.go
,看看輸出的文件是什麼?後端
筆者以這個文件爲例https://github.com/qiniu/goc/blob/master/goc.go
, 獲得如下結果:數組
package main import "github.com/qiniu/goc/cmd" func main() {CoverageVariableName.Count[0]++; cmd.Execute() } var CoverageVariableName = struct { Count [1]uint32 Pos [3 * 1]uint32 NumStmt [1]uint16 } { Pos: [3 * 1]uint32{ 21, 23, 0x2000d, // [0] }, NumStmt: [1]uint16{ 1, // 0 }, }
能夠看到,執行完以後,源碼裏多了個CoverageVariableName
變量,其有三個比較關鍵的屬性:架構
* `Count` uint32數組,數組中每一個元素表明相應基本塊(basic block)被執行到的次數 * `Pos` 表明的各個基本塊在源碼文件中的位置,三個爲一組。好比這裏的`21`表明該基本塊的起始行數,`23`表明結束行數,`0x2000d`比較有趣,其前16位表明結束列數,後16位表明起始列數。經過行和列能惟一肯定一個點,而經過起始點和結束點,就能精確表達某基本塊在源碼文件中的物理範圍 * `NumStmt` 表明相應基本塊範圍內有多少語句(statement) `CoverageVariableName`變量會在每一個執行邏輯單元設置個計數器,好比`CoverageVariableName.Count[0]++`, 而這就是所謂插樁了。經過這個計數器能很方便的計算出這塊代碼是否被執行到,以及執行了多少次。相信你們必定見過表示go覆蓋率結果的coverprofile數據,相似下面: `github.com/qiniu/goc/goc.go:21.13,23.2 1 1` 這裏的內容就是經過相似上面的變量`CoverageVariableName`獲得。其基本語義爲 "**文件:起始行.起始列,結束行.結束列 該基本塊中的語句數量 該基本塊被執行到的次數**"
依託於go語言官方強大的工具鏈,你們能夠很是方便的作單測覆蓋率收集與統計。可是集測/E2E就不是那麼方便了。不過好在咱們如今有了https://github.com/qiniu/goc。模塊化
關於單測這塊,深刻go源碼,咱們會發現go test -cover
命令會自動生成一個_testmain.go
文件。這個文件會Import各個插過樁的包,這樣就能夠直接讀取插樁變量,從而計算測試覆蓋率。實際上goc
也是相似的原理(PS: 關於爲什麼不直接用go test -c -cover
方案,能夠參考這裏https://mp.weixin.qq.com/s/DzXEXwepaouSuD2dPVloOg)。工具
不過集測時,被測對象一般是完整產品,涉及到多個long running的後端服務。因此goc在設計上會自動化會給每一個服務注入HTTP API,同時經過服務註冊中心goc server
來管理全部被測服務。如此的話,就能夠在運行時,經過命令goc profile
實時獲取整個集羣的覆蓋率結果,當真很是方便。測試
總體架構參見:
ui
技術須要爲企業價值服務,否則就是在耍流氓。能夠看到,目前玩覆蓋率的,主要有如下幾個方向:
度量 - 深度度量,各類包,文件,方法度量,都屬於該體系。其背後的價值在於反饋與發現。反饋測試水平如何,發現不足或風險並予以提升。好比常見的做爲流水線准入標準,發佈門禁等等。度量是基礎,但不能止步於數據。覆蓋率的終極目標,是提升測試覆蓋率,尤爲是自動化場景的覆蓋率,並一以貫之。因此基於此,業界咱們看到,作的比較有價值的落地形態是增量覆蓋率的度量。goc diff 結合Prow平臺也落地了相似的能力,若是您內部也使用Kubernetes,不妨嘗試一下。固然同類型的比較知名的商業化服務,也有CodeCov/Coveralls等,不過目前她們多數是侷限在單測領域。
精準測試方向 - 這是個很大的方向,其背後的價值邏輯比較清晰,就是創建業務到代碼的雙向反饋,用於提高測試行爲的精準高效。但這裏其實含有悖論,懂代碼的同窗,大機率不須要無腦反饋;不能深刻到代碼的同窗,你給代碼級別的反饋,也效果不大。因此這裏落地姿式很重要。目前業界沒還看到有比較好的實踐例子,大部分都是解決特定場景下的問題,有必定的侷限。
而相較於落地方向,做爲廣大研發同窗,下面這些最佳實踐可能對您更有價值:
谷歌有篇博客(參考資料)提到,其經驗代表,重視代碼覆蓋率的團隊一般會更加容易培養卓越工程師文化,由於這些團隊在設計產品之初就會考慮可測性問題,以便能更輕鬆的實現測試目標。而這些措施反過來會促使工程師編寫更高質量的代碼,更注重模塊化。
最後,歡迎點擊左下角詳情按鈕,加入七牛雲Goc交流羣,咱們一塊兒聊聊goc,聊聊研發效能那些事。
參考資料