多年來,在航空電子工業領域,覆蓋率分析技術已經在復雜的軟件控制系統錯誤檢測方面取得了非常有效的業績?,F在,汽車工業也在考慮在軟件控制方面的測試質量和不斷增加的費用之間選擇。如果能夠借鑒航空電子工業領域中的經驗和教訓將是一種明智的選擇。
有很多不同類型和級別的覆蓋率。經常被提及的術語是函數覆蓋率,這是一個用來報告你是否調用過每一個函數的度量標準。這種覆蓋率有助于在測試的初級階段確保軟件的所有部分達到一些基本的覆蓋率和消除一些明顯的不足。
語句覆蓋——也稱為線性覆蓋、段覆蓋或者基本塊覆蓋,它可用來說明每一個可執行語句是否被執行,基本塊覆蓋和語句覆蓋是一致的,被測的代碼單元是沒有分支的序列。這大大的擴充了覆蓋圖的范圍,雖然僅僅是平面圖。
語句覆蓋是最容易達到100%的覆蓋度量指標。它能覆蓋整個源代碼并且幫助用戶發現存在于程序中很少運行到的代碼段中的錯誤。雖然它相對來說容易達到100%,不需要花費昂貴的費用和資源,但是它仍然能夠顯著的增強我們在源代碼的正確性方面的信心。然而,簡單的實現100%的語句
覆蓋率意味者仍然有通過這些語句的潛在
的路徑沒有被執行,語句覆蓋不能測量這些路徑。
語句覆蓋是不能夠辨認很多的控制結構。例如,下面的這段C/C++代碼,在沒有一個測試用例使condition變量成為false的情況下,語句覆蓋就認為這個代碼被充分覆蓋了;實際上,如果一旦condition為false,這個代碼將出錯。這是語句覆蓋的一個非常嚴重的缺點。而If語句的使用是十分普遍的。
int* p = NULL;
if (condition)
p = &variable;
*p = 123;
語句覆蓋也不能告訴我們循環是否在終止時退出,它僅僅說明執行了循環體。因為像do-while這樣的循環會首先執行循環體一次,語句覆蓋認為它們是沒有分支的語句。
語句覆蓋率也忽略邏輯操作符(||和$$)。而且,語句覆蓋也不能辨認連續的開關語句標號。為了達到更加完整和精確的覆蓋,至少應用二維覆蓋圖,顯然需要分解判定條件。
if(condition1&&(condition2|| function1()))
statement1;
else
statement2;
在除安全苛刻性應用系統以外的其它所有情況下,分析單個的條件將可以有效的涵蓋其它的覆蓋所能達到的狀況??紤]一下在真實測試中使用“白盒測試”技術,在錯誤預防方面所能帶來的益處。
如何到達充分的覆蓋
在我們以加快上市時間、快速改善產品品質為目的進行生產力提升的同時,怎樣才能進行徹底的覆蓋呢?
通常不需要太多的努力便能實現語句覆蓋和分支覆蓋的一致(盡管不可行分支和代碼可能沒被發現),但是路徑測試覆蓋率經常會滯后于語句和分支覆蓋率,這是因為需要有苛刻的測試策略才能實現路徑測試覆蓋的最大化。
如果,路徑測試覆蓋能達到一致,這將大大的減少保留在程序中的未發現的錯誤。最大限度的路徑測試覆蓋對于一個程序的測試是比較徹底的,而且路徑測試覆蓋非常擅長發現存在于循環結構中的錯誤。實行對每一個語句的覆蓋并不需要實現對整個循環的覆蓋——而只需要一個直接貫穿的路徑。對每個分支的測試能保證循環至少被執行了一次,但是如果要對每個路徑進行測試卻需要循環至少被執行兩次。對于高可靠性代碼,推薦路徑測試覆蓋的最大化。
顯然在提高軟件質量和可靠性方面,路徑測試覆蓋技術是最有效的。這樣最大限度的路徑測試覆蓋將降低其它相關覆蓋測試的成本。
越來越多的軟件開發者在轉向商業的軟件測試工具來協助復雜的測試過程。有些軟件也集成了規則分析和其它的靜態分析技術來進行單元級(單個函數)到子系統級以及系統級(多文件)測試。
需要覆蓋率工具提供什么功能呢?
1. 能進行全面地覆蓋分析(最好能識別不可行代碼和不可達代碼)。
2. 能從單元級開始向上輔助自動測試用例/向量生成工具進行覆蓋分析。
3. 能提供直觀的可視化的報告以便于工程分析和指導。
結合工具的使用,開發者考慮按照下面的步驟將能更高效、低成本的到達覆蓋分析的目的:
第一步:根據對被測程序的期望實現功能的了解來構造最有可能的功能測試。這些應該從軟件需求說明書、軟件規格或用戶文檔獲得。在加載測試數據的情況下,應該能夠通過測試工具監控源代碼的執行。當實現功能測試的數據用完后,檢查覆蓋率來發現程序中的哪些部分仍然沒有被測到。應該進一步的構造測試數據并進行執行、分析。覆蓋率會隨著每一組測試數據的執行而累加并且每一組測試數據都會顯示執行了程序中的哪些部分。
上面的過程應該一直持續到進行功能測試的數據被執行完或者達到所需的測試度量標準。如果是前一種情況(測試數據執行完)那么進行第二步;否則的話(達到測試度量標準的要求)那么任務就完成了。
第二步:檢查測試覆蓋度量指標。如果語句覆蓋率沒有達到完全覆蓋(也就是說不是每條語句都被執行了),那么可能是由于某個特殊的用例運行失敗,錯誤退出,等造成的。由于這些可能性的存在,需要對執行歷史剖面進行累積,因為為了將代碼中的每一行都執行到,將程序執行多次通常是必須的。通常功能測試只能覆蓋程序中40%到60%的可執行語句。
當語句覆蓋達到完全,每一條語句都被執行時,便可進行第三步。
第三步:檢查所有沒有被執行的分支。通常這些分支中的一部分可以通過構造專門的用例實現對它們的測試。因為為找出程序中未執行分支而進行的程序分析和為了找出程序中的未執行路徑所要做得分析工作很相似,所以在將分支測試這種策略充分實施后再進行第四步——測試路徑覆蓋,將更加節約成本。
第四步:有些沒有執行到的分支和路徑,是由于相關的測試用例只有在程序執行出錯或者計算出錯的錯誤狀態下才能實現。這些通常是和程序的冗余保護設計相關,這樣的路徑應該完整的保留。
最后:
在進一步的檢查后會發現,通常很多沒有被執行的路徑都是不可行的,也就是說,在使用任何測試數據的情況下這些路徑都不可能被執行到。這意味著代碼的相關部分應該重新寫,因為這些代碼要么是無效的要么是不正確的。此外,當這些代碼重寫后,和這些代碼相關的其它一些測試路徑可能也會被去掉。如果是由于上面已知的原因,導致測試路徑不能被執行到,那么即使沒有達到覆蓋率標準,這些測試路徑也是可以忽略不計的。
一旦不可行測試路徑被去掉,那么源代碼將會更加有效、健壯并且占用更少的空間。
原文轉自:http://www.anti-gravitydesign.com