單元測(cè)試代碼覆蓋率解析
前言
在做單元測(cè)試時(shí),代碼覆蓋率常常被拿來作為衡量測(cè)試好壞的指標(biāo),甚至,用代碼覆蓋率來考核測(cè)試任務(wù)完成情況,比如,代碼覆蓋率必須達(dá)到80%或 90%。于是乎,測(cè)試人員費(fèi)盡心思設(shè)計(jì)案例覆蓋代碼。用代碼覆蓋率來衡量,有利也有有弊。本文我們就代碼覆蓋率展開討論,也歡迎同學(xué)們踴躍評(píng)論。
首先,讓我們先來了解一下所謂的“代碼覆蓋率”。我找來了所謂的定義:
代碼覆蓋率 = 代碼的覆蓋程度,一種度量方式。
上面簡短精悍的文字非常準(zhǔn)確的描述了代碼覆蓋率的含義。而代碼覆蓋程度的度量方式是有很多種的,這里介紹一下最常用的幾種:
1. 語句覆蓋(StatementCoverage)
又稱行覆蓋(LineCoverage),段覆蓋(SegmentCoverage),基本塊覆蓋(BasicBlockCoverage),這是最常用也是最常見的一種覆蓋方式,就是度量被測(cè)代碼中每個(gè)可執(zhí)行語句是否被執(zhí)行到了。這里說的是“可執(zhí)行語句”,因此就不會(huì)包括像C++的頭文件聲明,代碼注釋,空行,等等。非常好理解,只統(tǒng)計(jì)能夠執(zhí)行的代碼被執(zhí)行了多少行。
需要注意的是,單獨(dú)一行的花括號(hào){} 也常常被統(tǒng)計(jì)進(jìn)去。語句覆蓋常常被人指責(zé)為“最弱的覆蓋”,它只管覆蓋代碼中的執(zhí)行語句,卻不考慮各種分支的組合等等。
假如你的上司只要求你達(dá)到語句覆蓋,那么你可以省下很多功夫,但是,換來的確實(shí)測(cè)試效果的不明顯,很難更多地發(fā)現(xiàn)代碼中的問題。
這里舉一個(gè)不能再簡單的例子,我們看下面的被測(cè)試代碼:
int foo(int a, int b)
{
return a / b;
}
假如我們的測(cè)試人員編寫如下測(cè)試案例:
TeseCase: a = 10, b = 5
測(cè)試人員的測(cè)試結(jié)果會(huì)告訴你,他的代碼覆蓋率達(dá)到了100%,并且所有測(cè)試案例都通過了。然而遺憾的是,我們的語句覆蓋率達(dá)到了所謂的100%,但是卻沒有發(fā)現(xiàn)最簡單的Bug,比如,當(dāng)我讓b=0時(shí),會(huì)拋出一個(gè)除零異常。
正因如此,假如上面只要求測(cè)試人員語句覆蓋率達(dá)到多少的話,測(cè)試人員只要鉆鉆空子,專門針對(duì)如何覆蓋代碼行編寫測(cè)試案例,就很容易達(dá)到主管的要求。當(dāng)然了,這同時(shí)說明了幾個(gè)問題:
1.主管只使用語句覆蓋率來考核測(cè)試人員本身就有問題。
2.測(cè)試人員的目的是為了測(cè)好代碼,鉆如此的空子是缺乏職業(yè)道德的。
3.是否應(yīng)該采用更好的考核方式來考核測(cè)試人員的工作?
為了尋求更好的考核標(biāo)準(zhǔn),我們必須先了解完代碼覆蓋率到底還有哪些,如果你的主管只知道語句覆蓋,行覆蓋,那么你應(yīng)該主動(dòng)向他介紹還有更多的覆蓋方式。比如:
2. 判定覆蓋(DecisionCoverage)
又稱分支覆蓋(BranchCoverage),所有邊界覆蓋(All-EdgesCoverage),基本路徑覆蓋(BasicPathCoverage),判定路徑覆蓋(Decision-Decision-Path)。它度量程序中每一個(gè)判定的分支是否都被測(cè)試到了。這句話是需要進(jìn)一步理解的,應(yīng)該非常容易和下面說到的條件覆蓋混淆。因此我們直接介紹第三種覆蓋方式,然后和判定覆蓋一起來對(duì)比,就明白兩者是怎么回事了。
3. 條件覆蓋(ConditionCoverage)
它度量判定中的每個(gè)子表達(dá)式結(jié)果true和false是否被測(cè)試到了。為了說明判定覆蓋和條件覆蓋的區(qū)別,我們來舉一個(gè)例子,假如我們的被測(cè)代碼如下:
int foo(int a, int b)
{
if (a < 10 || b < 10) // 判定
{
return 0; // 分支一
}
else
{
return 1; // 分支二
}
}
設(shè)計(jì)判定覆蓋案例時(shí),我們只需要考慮判定結(jié)果為true和false兩種情況,因此,我們?cè)O(shè)計(jì)如下的案例就能達(dá)到判定覆蓋率100%:
TestCaes1: a = 5, b = 任意數(shù)字 覆蓋了分支一 TestCaes2: a = 15, b = 15 覆蓋了分支二
設(shè)計(jì)條件覆蓋案例時(shí),我們需要考慮判定中的每個(gè)條件表達(dá)式結(jié)果,為了覆蓋率達(dá)到100%,我們?cè)O(shè)計(jì)了如下的案例:
TestCase1: a = 5, b = 5 true, true TestCase4: a = 15, b = 15 false, false
通過上面的例子,我們應(yīng)該很清楚了判定覆蓋和條件覆蓋的區(qū)別。需要特別注意的是:條件覆蓋不是將判定中的每個(gè)條件表達(dá)式的結(jié)果進(jìn)行排列組合,而是只要每個(gè)條件表達(dá)式的結(jié)果true和false測(cè)試到了就OK了。因此,我們可以這樣推論:完全的條件覆蓋并不能保證完全的判定覆蓋。比如上面的例子,假如我設(shè)計(jì)的案例為:
TestCase1: a = 5, b = 15 true, false 分支一 TestCase1: a = 15, b = 5 false, true 分支一
我們看到,雖然我們完整的做到了條件覆蓋,但是我們卻沒有做到完整的判定覆蓋,我們只覆蓋了分支一。上面的例子也可以看出,這兩種覆蓋方式看起來似乎都不咋滴。我們接下來看看第四種覆蓋方式。
4. 路徑覆蓋(PathCoverage)
又稱斷言覆蓋(PredicateCoverage)。它度量了是否函數(shù)的每一個(gè)分支都被執(zhí)行了。 這句話也非常好理解,就是所有可能的分支都執(zhí)行一遍,有多個(gè)分支嵌套時(shí),需要對(duì)多個(gè)分支進(jìn)行排列組合,可想而知,測(cè)試路徑隨著分支的數(shù)量指數(shù)級(jí)別增加。比如下面的測(cè)試代碼中有兩個(gè)判定分支:
int foo(int a, int b)
{
int nReturn = 0;
if (a < 10)
{// 分支一
nReturn += 1;
}
if (b < 10)
{// 分支二
nReturn += 10;
}
return nReturn;
}
對(duì)上面的代碼,我們分別針對(duì)我們前三種覆蓋方式來設(shè)計(jì)測(cè)試案例:
a. 語句覆蓋
TestCase a = 5, b = 5 nReturn = 11
語句覆蓋率100%
b. 判定覆蓋
TestCase1 a = 5, b = 5 nReturn = 11 TestCase2 a = 15, b = 15 nReturn = 0
判定覆蓋率100%
c. 條件覆蓋
TestCase1 a = 5, b = 15 nReturn = 1 TestCase2 a = 15, b = 5 nReturn = 10
條件覆蓋率100%
我們看到,上面三種覆蓋率結(jié)果看起來都很酷!都達(dá)到了100%!主管可能會(huì)非常的開心,但是,讓我們?cè)偃プ屑?xì)的看看,上面被測(cè)代碼中,nReturn的結(jié)果一共有四種可能的返回值:0,1,10,11,而我們上面的針對(duì)每種覆蓋率設(shè)計(jì)的測(cè)試案例只覆蓋了部分返回值,因此,可以說使用上面任一覆蓋方式,雖然覆蓋率達(dá)到了100%,但是并沒有測(cè)試完全。接下來我們來看看針對(duì)路徑覆蓋設(shè)計(jì)出來的測(cè)試案例:
TestCase1 a = 5, b = 5 nReturn = 0 TestCase2 a = 15, b = 5 nReturn = 1 TestCase3 a = 5, b = 15 nReturn = 10 TestCase4 a = 15, b = 15 nReturn = 11
路徑覆蓋率100%
太棒了!路徑覆蓋將所有可能的返回值都測(cè)試到了。這也正是它被很多人認(rèn)為是“最強(qiáng)的覆蓋”的原因了。
還有一些其他的覆蓋方式,如:循環(huán)覆蓋(LoopCoverage),它度量是否對(duì)循環(huán)體執(zhí)行了零次,一次和多余一次循環(huán)。剩下一些其他覆蓋方式就不介紹了。
總結(jié)
通過上面的學(xué)習(xí),我們?cè)倩仡^想想,覆蓋率數(shù)據(jù)到底有多大意義。我總結(jié)了如下幾個(gè)觀點(diǎn),歡迎大家討論:
a. 覆蓋率數(shù)據(jù)只能代表你測(cè)試過哪些代碼,不能代表你是否測(cè)試好這些代碼。(比如上面第一個(gè)除零Bug)
b. 不要過于相信覆蓋率數(shù)據(jù)。
c. 不要只拿語句覆蓋率(行覆蓋率)來考核你的測(cè)試人員。
d. 路徑覆蓋率 > 判定覆蓋 > 語句覆蓋
e. 測(cè)試人員不能盲目追求代碼覆蓋率,而應(yīng)該想辦法設(shè)計(jì)更多更好的案例,哪怕多設(shè)計(jì)出來的案例對(duì)覆蓋率一點(diǎn)影響也沒有。
以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持我們。
上一篇:C語言實(shí)現(xiàn)順序表的順序查找和折半查找
欄 目:C語言
下一篇:C語言鏈表實(shí)現(xiàn)學(xué)生管理系統(tǒng)
本文標(biāo)題:單元測(cè)試代碼覆蓋率解析
本文地址:http://www.jygsgssxh.com/a1/Cyuyan/259.html
您可能感興趣的文章
- 01-10使用OpenGL實(shí)現(xiàn)3D立體顯示的程序代碼
- 01-10大數(shù)(高精度數(shù))模板(分享)
- 01-10顯示任何進(jìn)程加載的DLL文件的代碼
- 01-10貪心算法 WOODEN STICKS 實(shí)例代碼
- 01-10基于C程序啟動(dòng)代碼的深入分析
- 01-10Linux C 獲取進(jìn)程退出值的實(shí)現(xiàn)代碼
- 01-10用c語言根據(jù)可變參數(shù)合成字符串的實(shí)現(xiàn)代碼
- 01-10基于C語言實(shí)現(xiàn)shell指令的詳解
- 01-10深入解析C中的數(shù)值與真假
- 01-10輸出1000以內(nèi)的素?cái)?shù)的算法(實(shí)例代碼)


閱讀排行
本欄相關(guān)
- 04-02c語言函數(shù)調(diào)用后清空內(nèi)存 c語言調(diào)用
- 04-02func函數(shù)+在C語言 func函數(shù)在c語言中
- 04-02c語言的正則匹配函數(shù) c語言正則表達(dá)
- 04-02c語言用函數(shù)寫分段 用c語言表示分段
- 04-02c語言中對(duì)數(shù)函數(shù)的表達(dá)式 c語言中對(duì)
- 04-02c語言編寫函數(shù)冒泡排序 c語言冒泡排
- 04-02c語言沒有round函數(shù) round c語言
- 04-02c語言分段函數(shù)怎么求 用c語言求分段
- 04-02C語言中怎么打出三角函數(shù) c語言中怎
- 04-02c語言調(diào)用函數(shù)求fibo C語言調(diào)用函數(shù)求
隨機(jī)閱讀
- 04-02jquery與jsp,用jquery
- 08-05dedecms(織夢(mèng))副欄目數(shù)量限制代碼修改
- 01-10C#中split用法實(shí)例總結(jié)
- 01-10使用C語言求解撲克牌的順子及n個(gè)骰子
- 01-10delphi制作wav文件的方法
- 01-10SublimeText編譯C開發(fā)環(huán)境設(shè)置
- 08-05DEDE織夢(mèng)data目錄下的sessions文件夾有什
- 01-11Mac OSX 打開原生自帶讀寫NTFS功能(圖文
- 01-11ajax實(shí)現(xiàn)頁面的局部加載
- 08-05織夢(mèng)dedecms什么時(shí)候用欄目交叉功能?


