尹黨輝,于佳偉,李 虎
(總后后勤科學研究所,北京 100071)
覆蓋測試,也稱為邏輯覆蓋測試,是軟件白盒測試的主要方法[1-3]。在一個軟件產品中,如果存在某些從來沒有被執(zhí)行過的代碼,那么這個軟件的質量是不可靠的[4],在從來沒有被執(zhí)行過的代碼中可能存在著使整個軟件崩潰的BUG而沒有被發(fā)現(xiàn)[5]。
覆蓋測試就是讓軟件的所有代碼都被執(zhí)行過至少一次,力爭在測試過程中發(fā)現(xiàn)那些非常隱秘的BUG,從一定程度上確保軟件的可靠性。
衡量覆蓋測試好壞的標準就是覆蓋率,覆蓋率越高,則認為測試所達到的效果越好。足夠高的覆蓋率可以增強對被測軟件的信心[6]。覆蓋率代表測試過程中被執(zhí)行的程序對象的百分比,其計算公式為
覆蓋率=(已執(zhí)行的程序對象的數(shù)量/程序中可執(zhí)行程序對象的總數(shù))×100%
語句覆蓋(statement coverage,SC)的含義是:選擇足夠多的測試數(shù)據(jù),使被測程序中每條語句至少執(zhí)行一次。語句覆蓋報告每個可執(zhí)行語句是否都被執(zhí)行過。這種測試準則的主要優(yōu)點是可以直接被用于對目標代碼進行測試,不要求對源代碼進行處理;語句覆蓋的主要缺點是它對某些控制機構不敏感。
可以通過語句所在文件的行號來唯一標識一條語句,語句是以行為單位的可以執(zhí)行代碼。如下面的代碼所示,如果第1行的代碼被執(zhí)行,則認為該語句被覆蓋。
語句覆蓋是衡量一個測試所達到的覆蓋率的最基本也是最簡單的方法。語句覆蓋率代表測試過程中被執(zhí)行的語句在被測程序中所占的百分比,其計算公式為
語句覆蓋率=(至少執(zhí)行了一次的語句總數(shù)/可執(zhí)行的語句總數(shù))×100%
語句覆蓋是最弱的邏輯覆蓋準則,即便語句覆蓋率達到了100%,也不能完全保證被測程序100%的被覆蓋。還是以上面一行程序為例,程序中如果if語句中的條件表達式不成立,則“j++”不可能被執(zhí)行,但在語句覆蓋來看,這一行語句是被覆蓋了的。
比語句覆蓋稍強的覆蓋標準是判定覆蓋(decision coverage,DC)。判定覆蓋的含義是:設計足夠多的測試用例,使得程序中的每個判定至少都獲得一次“真值”或“假值”,因此判定覆蓋又稱為分支覆蓋。該測試準則只報告控制結構中被測試的布爾表達式為真或假。整個布爾表達式看作為一個trueor-false謂詞,不管他是否含有邏輯“and”或邏輯“or”。它的缺點是該測試值忽略布爾表達式內的分支,特別是當布爾表達式簡化時。
從程序運行流程的角度來看,程序有順序、分支和循環(huán)3種基本流程,從一定意義上說循環(huán)也是分支的一種。最典型的分支就是if語句,以下面的程序為例:
由于if語句,使得程序流程產生了兩個明顯的分支,一支是“j++;”,另一支是“k++;”。
以上面的程序為例,共有如下4個分支:1→2;3→4;2→5;4→5。判定覆蓋是衡量一個測試所達到的覆蓋率的比較可靠的方法,如果一個程序的所有分支都被執(zhí)行過一遍,那么可以認為程序中所有的代碼毫無遺漏的被執(zhí)行過一遍。判定覆蓋率代表被執(zhí)行的分支在被測程序的所有分支中所占的百分比,其計算公式為
判定覆蓋率=(至少執(zhí)行了一次的分支總數(shù)/可執(zhí)行的分支總數(shù))×100%
雖然判定覆蓋是覆蓋測試中比較可靠的方法,但是判定覆蓋的代價很高,達到很高的覆蓋率非常困難;不過分支覆蓋有一個優(yōu)點是可以實現(xiàn)對go_to,switch語句以及函數(shù)調用等復雜程序邏輯的覆蓋。
在設計程序中,一個判定語句往往是由多個條件組合而成的復合判定。這樣,為了更徹底地實現(xiàn)邏輯覆蓋,可以采用條件覆蓋(condition coverage,CC)的標準。條件覆蓋的含義是:構造一組測試用例,使得每一判定語句中每個邏輯條件的可能值至少滿足一次。條件覆蓋報告每個布爾子表達式的真假結果,這些子表達式是由邏輯and和邏輯or組成的,條件覆蓋測試相互獨立的子表達式。此測試準則值類似于判定覆蓋,但對控制流更敏感。然而,完全的條件覆蓋并不保證完全的判定覆蓋。
條件判定組合覆蓋(condition decision coverage,CDC)的含義是:設計足夠的測試用例,使得判定中每個條件的所有可能(真/假)至少出現(xiàn)一次,并且每個判定本身的判定結果(真/假)也至少出現(xiàn)一次。
多條件覆蓋(multiple condition coverage,MCC)也稱條件組合覆蓋,它的含義是:設計足夠多的測試用例,使得每個判定中條件的可能組合都至少出現(xiàn)一次。顯然滿足多條件覆蓋的測試用例是一定滿足判定覆蓋、條件覆蓋和條件判定組合覆蓋的。當一個程序中判定語句較多時,其條件取值的組合數(shù)目是非常大的。
修正條件判定覆蓋(modified condition/decision coverage,MCDC)是由歐美的航空/航天制造廠商和使用單位聯(lián)合制定的“航空運輸和裝備系統(tǒng)軟件認證標準”,目前在國外的國防、航空航天領域應用廣泛。這個覆蓋度量需要足夠的測試用例來確定各個條件能夠影響到包含的判定結果。它要求滿足兩個條件:首先,每一個程序模塊的入口和出口點都要考慮至少要被調用一次,每個程序的判定到所有可能的結果值要至少轉換一次;其次,程序的判定被分解為通過邏輯操作符(and、or)連接的bool條件,每個條件對于判定的結果是獨立的。此測試準則要求用足夠的測試用例,驗證每個可能影響判斷的條件。
修正條件判定覆蓋可以發(fā)現(xiàn)3類錯誤:“與”、“或”被誤寫;一個變量被誤寫為它的否定;一個表達式被誤寫為它的否定。
例如,A and(B or C)是一個判定,A、B、C 均為條件,其全部的條件組合見表1。
表1 條件組合表1)
測試用例對(1,5),(2,6),(3,7)都可表明條件 A獨立地影響判定結果;測試用例對(2,4)可表明條件B獨立地影響判定結果;測試用例(3,4)可表明條件C獨立地影響判定結果;因此,測試用例集(1,2,3,4,5)可滿足上述判定的修正的條件判定覆蓋率。
路徑覆蓋(path coverage,PC)報告函數(shù)中每個可能的路徑是否走過。一個路徑是唯一的一個分支序列,從函數(shù)入口到退出。由于循環(huán)體引入很大的路徑個數(shù),此測試準則僅考慮有限循環(huán)的可能性。此測試準則的大量變體與循環(huán)是有關的。邊界-內部路徑測試考慮循環(huán)的兩種可能性:零次循環(huán)和多于零次的循環(huán)。對于do-while循環(huán),兩種可能性是一次循環(huán)和多于一次循環(huán)。
從以上介紹可看出,這7種覆蓋策略的嚴格順序如圖1所示[7]。
圖1 覆蓋策略的嚴格順序
本測試的測試環(huán)境是C++test 9.0,加載的是Virtual C++6.0工程,測試用例由C++test測試工具自動生成。主要驗證了C++test對判定“A and(B or C)”的邏輯覆蓋測試。
程序源碼如圖2,覆蓋測試結果如圖3。在圖3中,C++test對語句覆蓋、判定覆蓋、條件覆蓋、修正條件1判定覆蓋、路徑覆蓋進行了統(tǒng)計分析。
在現(xiàn)實應用中,通常一個工程的源程序都遠比本文所列舉的源程序復雜的多,要實現(xiàn)上面任一個覆蓋準則的100%的覆蓋率都是不可行的[8]。通常都用覆蓋測試工具來自動實施,即測試人員只負責測試用例的編寫與執(zhí)行,測試工具自動記錄程序的覆蓋執(zhí)行范圍并給出覆蓋率,這就大大降低了測試人員的勞動強度。測試由于其本身的復雜性仍然是非常繁瑣的。現(xiàn)在的一些商品化工具還提供一些案例的自動生成,可以進一步降低測試人員的勞動強度。
圖2 程序源碼
圖3 覆蓋測試結果
[1]Jorgensen P C.軟件測試[M].2版.韓柯,杜旭濤,譯.北京:機械工業(yè)出版社,2003.
[2]鄭人杰.計算機軟件測試技術[M].北京:清華大學出版社,1992.
[3]尹黨輝.嵌入式軟件測試技術研究[J].中國測試技術,2011(8):74-77.
[4]朱少民.軟件質量保證和管理[M].北京:清華大學出版社,2007.
[5]姚礪,束永安,葉澄清.面向對象軟件覆蓋量度的研究和軟件測試工具的實現(xiàn)[J].計算機研究與發(fā)展,2002,39(8):1017-1022.
[6]黎連生,王華,李淑春.軟件測試與測試技術[M].北京:清華大學出版社,2009.
[7]陳麗蓉,熊光澤,羅蕾,等.嵌入式軟件的覆蓋測試[J].單片機與嵌入式系統(tǒng)應用,2002(11):8-11.
[8]柳純錄.軟件評測師教程[M].北京:清華大學出版社,2005.