代碼覆蓋率是衡量軟件測試完成情況的指標,通常基于測試過程中已檢查的程序源代碼比例 計算得出。代碼覆蓋率可以有效避免包含未測試代碼的程序被發布。
代碼覆蓋率能不能提高軟件的可靠性?答案是肯定的,代碼的覆蓋率分析是保證軟件質量最簡 便易行的方法。
代碼覆蓋率等級
代碼覆蓋率可以通過多種方法測量。最常用的是測量以下一個或多個指標:語句覆蓋率,分支 覆蓋率,修訂的條件/判定覆蓋率(MC/DC)。以下章節中將逐一詳解這些代碼覆蓋率。
語句覆蓋率
語句覆蓋率用來度量被測代碼中的可執行語句是否被執行到,它并不考慮循環或者條件語句, 只針對語句度量可執行代碼。應當特別注意的是:“語句”并不等同于代碼行。
一般情況下,對于 C,C++,Java或Ada,分號代表語句結束。在某些情況下,一條語句會跨越多 行代碼。語句覆蓋率可以有效度量可執行代碼是否被執行,但同時也有一定的局限性。
語句覆蓋率的局限
考慮如下圖1的代碼段:
int* p = NULL;
if (condition)
p = &variable;
*p = 123;
圖 1 – 語句覆蓋局限代碼示例
如果“condition”為true,那么就有可能達到100%的語句覆蓋,然而這個測試用例忽略了另 一種情況:如果“condition”為假,程序將引用空指針,因此,雖然語句覆蓋率是一個很好 的度量指標,它仍舊是入門級的代碼覆蓋率。理想情況下,即使“condition”為false,測試 用例也應當被計算。
分支覆蓋率
分支覆蓋率用來度量程序中所有的判定和分支以及相應的輸出是否都被測試執行到,例如 “if”語句必須將“true”和“false”都考慮到以覆蓋所有的輸出。如果只有一個路徑被執行,那么覆蓋率將被標記為部分執行。
和語句覆蓋率類似,分支覆蓋浪費也有一些需要注意的細節,尤其在針對“惰性求值”的編程語言時,惰性求值是將代碼的求值操作延遲到需要結果值時再進行的一項技術。
分支覆蓋率的局限
典型的情況是當有復雜的布爾表達式的“惰性求值”出現時,如下圖2的代碼片段:
int* p = NULL;
if (condition1 && (condition2 || function1(*p)))
statement1;
else
圖 2 – 分支覆蓋率局限代碼示例
考慮“condition1”為假的情況,惰性求值將不會度量“condition2”或,此種情況同樣會導致 代碼“if (condition1 && (condition2 || function1(*p)))”的分支覆蓋率計算錯誤。
繼續考慮“condition1”和“condition2”都為真的情況。惰性求值將再次導致“function1(*p)” 不會被度量,也同樣會導致代碼“if (condition1 && (condition2 || function1(*p)))”的分支覆蓋率 計算錯誤。在此種情況下,有可能出現分支覆蓋率為100%但軟件中仍有潛在缺陷的情況。
修訂條件/判定覆蓋率(MC/DC)
MC/DC是一種特殊的分支覆蓋率,它不但會使用分支覆蓋率報告復雜條件下的true和false輸出,同時也會報告復雜條件下的全部分支條件輸出。
MC/DC最初由波音公司創建,用于航空軟件中DO-178B的A級認證。通過對所有的子條件輸出分支的獨立證明,有效解決了惰性求值帶來的問題。
繼續討論代碼示例2,我們需要在“condition2”和“function1(*p)”固定的條件下驗證“condition1” 的“true”和“false”判定分支,之后繼續固定“condition1”和“function1(*p)”驗證“condition2” 的判定分支。
同樣的,讓我們在固定“condition1”和“condition2”的條件下討論 “function1(*p)”。在其他分支條件固定的情況下驗證某個分支條件的“true”和“false”值稱作“MC/DC對”。MC/DC對一般使用MC/DC真值表描述。表1就是一個MC/DC真值表示例。
在軟件開發的不同階段獲取覆蓋率
軟件測試有很多種類,本文將其簡要的分為三類:
》 系統/函數測試: 測試集成后的整個應用
》 集成測試::測試集成的子系統
》 單元測試:測試一個或多個文件或類
每個軟件項目在系統測試的過程中都會模擬最終用戶的操作對源代碼做一些系統測試。導致軟件發布后仍舊存在缺陷最重要的一個原因通常是程序在運行過程中遇到了非預期的,即沒有測試的輸入組合。
很多軟件項目并不是沒有做集成測試或者單元測試。只是在完成集成測試或單元測試后,開發團隊可能苦于為隔離程序中的單個或多個文必須所需的大量測試代碼量。
對于最嚴格的單元測試和集成測試來說,最終生成的測試代碼量比待測代碼量還要龐大是很經常出現的情況。因此,這兩種級別的測試普遍適用于關鍵和高安全領域,例如:航空航天、醫療、交通運輸、工業過程控制、高速汽車等。此類軟件中包含大量的嵌入式應用軟件。
關鍵領域的結構化測試流程一般會將需求的級別高低作為重點,代碼覆蓋率因而會在這種“基于需求”的測試中進行分析。在許多項目中,高等級的需求最先被測試。此時代碼覆蓋率可以被用來檢測和報告所達到的覆蓋比例。
然而不幸的是,在系統測試和功能測試階段想要達到100%的代碼覆蓋率幾乎是不可能的。通常情況下系統測試和功能測試只能達到60%-70%的代碼覆蓋率,剩余30%-40%的代碼覆蓋率需要在單元測試和集成測試階段才能夠完成。
單元測試使用包含驅動和樁的測試代碼隔離系統中的特定函數,同時使用測試用例模擬這些函數的執行。這些所謂的“低等級測試需求” 對被測試代碼提供了更高的控制,可以提高先前執行的系統測試覆蓋率(甚至能達到100%)。因此,在不同的測試之間共享覆蓋率數據是非常有必要的。
嵌入式環境中獲取覆蓋率帶來的挑戰
常言道“有得必有失”,在嵌入式環境獲取代碼覆蓋率的問題上,要付出的代價是對待測代碼額外的插樁工作。
插樁是將額外的代碼添加到程序中,從而實現測試過程中的覆蓋率收集和分析操作。
由于插樁的相關操作將導致程序源代碼增多,進而延長程序的執行時間,因而需要預測插樁后的源代碼的覆蓋范圍預測,尤其當測試實時嵌入式系統環境時,此項工作就更為重要。
事實上,要精準的預測程序文件插樁的影響幾乎是不可能的。沒有算法支持(也不可能有)。 每個系統都包含很多的變量,具有獨立唯一的復雜性。當然,對于典型的示例系統來說,獲取一組準確的估計還是可能實現的。
在共享環境中獲取覆蓋率數據
在嵌入式環境下管理代碼覆蓋率的主要問題在于如何配置內存以容納額外的插樁代碼。
VectorCAST針對大量示例代碼評估后發現添加了上文中提出的各種覆蓋率額外配置之后,源代碼量增長量普遍達到了10%。對于絕大多數的32位目標板,這并不是一個很大的問題,但對于存儲容量有限的8位或者16位目標板來說,幾乎可以肯定這會是一個問題。
為了降低可執行文件的大小,各種各樣的代碼插樁技術被發明出來,針對不同大小的存儲區域有不同的數據采集技術。植入存儲器內部的收集系統可以用于監測被檢測到的代碼。這是插樁技術中保證使用最少RAM的關鍵技術。
-
嵌入式
+關注
關注
5082文章
19123瀏覽量
305151 -
JAVA
+關注
關注
19文章
2967瀏覽量
104749 -
C++
+關注
關注
22文章
2108瀏覽量
73646
發布評論請先 登錄
相關推薦
評論