《Unit Testing》1.3 使用覆盖率指标来度量测试套件的好坏
使用覆蓋率來度量測試套件(Test Suite)的質量
有兩種比較流行的測試覆蓋率的度量方法:
代碼覆蓋率
分支覆蓋率
覆蓋率度量會顯示一個測試套件(Test Suite)會執行多少代碼,范圍從 0 至 100%。
除了上述兩種方法之外,還有很多其它的度量方法。它們都是被用來評估一個測試套件的質量的。
?
通常人們會認為,這個覆蓋率越高越好。不幸的是,這沒那么簡單,覆蓋率度量確實能提供非常有價值的反饋,但是它們無法有效的評估出測試套件的質量。這一點與代碼可進行單元測試的能力一樣:覆蓋率度量是一個非常好的負向指示(能評估出測試套件是否較差),但它無法評估出測試套件是否很好。
?
代碼覆蓋率度量
第一種,也是使用最多的度量方式就是代碼覆蓋率(code coverage,也叫測試覆蓋率 test coverage)。它的公式如下:
?
?
例如:
?
?
該測試對上面的有效代碼(共 5 行,8、9、10、12、13)的覆蓋率達到了 80%(8、9、12、13)。
?
如果我重構一下代碼,如下圖所示呢:
可以看到有效代碼行數變成了 3 行(8、9、10),它們都是綠色,說明都被覆蓋了。從工具也可以看到覆蓋率變成了 100%:
?
所以,代碼覆蓋率確實變化了,達到了 100%。但是測試套件的質量提高了嗎?當然沒有,我只是在方法內部重新羅列了一下代碼,而測試仍然只驗證了相同數量的可能結果。
?
分支覆蓋率度量
另一種覆蓋率度量方法是分支覆蓋率。其公式如下:
?
?
想要使用復制覆蓋率,你得想辦法把代碼里所有可能的分支求和,然后再檢測測試走了多少分支。
?
例子:
還是之前的例子,IsStringLong 方法里面一共有兩種情況,也就是兩個分支。而測試只會運行小于等于 5 這種情況,所以分支覆蓋率為 50%:
?
注意:分支覆蓋率里面只考慮分支數量,并不考慮所執行的代碼行數。
?
覆蓋率度量的問題
盡管分支覆蓋率的結果比代碼覆蓋率更有用一些,但是仍然無法依賴它們中的任何一個來決定測試套件的質量:
無法保證測試會驗證被測試系統(SUT,System Under Test)所有可能的結果。
沒有一種覆蓋率度量法可以測試外部庫的代碼路徑。
?
為了讓代碼路徑真正被測試,而不僅僅是路過執行,單元測試必須有適當的斷言。
?
例子:
這段代碼其實產生了兩個結果,分別是 13 和 15 行,只有第 15 行的結果被測試了,而第 13 行的結果(第 7 行的屬性)并沒有被驗證。
而兩種測試覆蓋率的結果仍然沒有變化,還是 100% 和 50%。
所以說,覆蓋率度量無法保證代碼會被測試,只能保證代碼會被執行而已。
?
但是,如果你確實考慮了每種可能,同時結合分支覆蓋率,那么是否能夠提供一個可靠的機制,來判斷測試套件的質量呢?很不幸,不能。
因為沒有任何覆蓋率度量方法能考慮外部庫中的代碼路徑。
?
例如:
這個測試里,分支覆蓋率達到了 100%,但是它沒考慮 .NET 提供的 int.Parse 這個方法的可能結果。對于 int.Parse 至少有以下幾種可能:
而我們只考慮了其中一種。所以您可能會遇到許多極端情況,并且無法查看測試是否將所有情況都考慮在內。
?
這并不是說覆蓋率度量應該考慮外部庫的代碼路徑(它們不應該),而是說明你不能指望這些度量來評估單元測試的質量好壞。覆蓋率度量無法判斷您的測試是否詳盡無遺; 也不能說明是否有足夠的測試。
?
特定的覆蓋率數字
要把覆蓋率度量當成一個指標,而不是一個目標。
就如同生病住院的病人,體溫高可能表示發燒,它是一個有用的觀察。但是醫院不能把不擇手段降低病人的體溫當成治病的目標。
?
通常,如果系統核心某塊的測試的覆蓋率較高的話是很好的,但是如果把高覆蓋率當成目標就不好了。
?
就個人而言:我認為覆蓋率低于 60% 肯定不好,這說明有大量的代碼未測試。但是更高的覆蓋率數字并不能代表什么。所以度量覆蓋率只是驗證測試套件質量的第一步而已。
總結
以上是生活随笔為你收集整理的《Unit Testing》1.3 使用覆盖率指标来度量测试套件的好坏的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 《Unit Testing》1.1 -1
- 下一篇: Linux创始人:v5.8是有史以来最大