變異測試是一種 fault-based 的軟件測試技術。這項技術已經廣泛研究並使用了三十余年。它為軟件測試貢獻了一系列方法,工具,和可靠的結果。本文將對變異測試進行深入的調查,分析它的優勢和不足之處,並對比幾種不同的變異測試方法,提出一些改進的建議。
下面用一個例子來解釋什么是變異測試,考慮以下代碼片段:
if(a && b) c = 1;
else c = 0;
條件運算符如果用||來替換&&,就會產生以下變異:
if(a || b) c = 1;
else c = 0;
為了殺死這個突變,需要滿足以下條件:
(1)測試數據必須對突變和原始程序引起的不同狀態覆蓋。如:a=1,b=0可以達到目的。
(2)c的值應該傳播到程序輸出,並被測試檢查。
弱突變覆蓋需滿足(1),強突變覆蓋需滿足(1)(2)。
下面進行正式的內容。
1 變異測試理論
1.1 兩個基本假設
變異測試旨在找出有效的測試用例,發現程序中真正的錯誤。在一個工程中,潛在BUG的數量是巨大的,通過生成突變體來全面覆蓋所有的錯誤是不可能的。所以,傳統的變異測試旨在尋找這些錯誤的子集,能盡量充分地近似描述這些BUG。這個理論基於兩條假設:Competent Programmer Hypothesis(CPH) 和 Coupling Effect(CE)。
CPH是指:假設編程人員是有能力的,他們盡力去更好地開發程序,達到正確可行的結果,而不是搞破壞。它關注的是程序員的行為和意圖。而CE(耦合效應)更加關注在變異測試中錯誤的類別。一個簡單的錯誤產生往往是由於一個單一的變異(例如句法錯誤),而一個龐大復雜的錯誤往往是由於多出變異所導致。復雜變異體往往是由諸多簡單變異體組合而成。
1.2 變異測試流程
在變異測試中,對於被測程序p,設定一個測試用例集合T。首先根據被測程序特征設定一系列變異算子;隨后通過在原有程序p上,執行變異算子生成大量變異體;接着從大量變異體中識別出等價變異體;然后在剩余的非等價變異體上執行測試用例集T中的測試用例,若可以檢測出所有非等價變異體,則變異測試分析結束,否則對未檢測出的變異體,需要額外設計新的測試用例,並添加到測試用例集T中。
基於上述傳統變異測試分析流程, 對其中的基本概念依次定義如下。
定義 1(變異算子) 在符合語法規則前提下, 變異算子定義了從原有程序生成差別極小程序(即變異體) 的轉換規則。表 1給出了一個典型的變異算子, 該變異算子將“+” 操作符變異為 “-” 操作符。選擇被測程序 p 中的條件表達式 a + b > c 執行該變異算子, 將得到條件表達式 a - b > c , 並生成變異體 p′ 。
Offutt和King在已有研究工作的基礎上,於 1987年針對 Fortran77首次定義了 22種變異算子,這些變異算子的簡稱和描述如表 2 所示。
這22種變異算子的設定為隨后其他編程語言變異算子的設定提供了重要的指導依據。在完成變異算子設計后,通過在原有被測程序上執行變異算子可以生成大量變異體M,在變異測試中,變異體一般被視為含缺陷程序。根據執行變異算子的次數,可以將變異體分為一階變異體和高階變異體,並分別定義如下。
定義 2 (一階變異體) 在原有程序 p 上執行單一變異算子並形成變異體 p′ ,則稱p′為p的一階變異體。
定義 3 (高階變異體) 在原有程序 p 上依次執行多次變異算子並形成變異體 p′ ,則稱 p′ 為 p 的高階變異體。若在 p 上依次執行 k 次變異算子並形成變異體 p′ , 則稱 p′ 為 p 的 k 階變異體。
高階變異體實例
定義 4 (可殺除變異體)若存在測試用例 t,在變異體 p′ 和原有程序 p 上的執行結果不一致, 則稱該變異體 p′ 相對於測試用例集 T 是可殺除變異體。
定義 5(可存活變異體) 若不存在任何測試用例t , 在變異體 p′ 和原有程序 p 上的執行結果不一致, 則稱該變異體 p′ 相對於測試用例集 T 是可存活變異體。一部分可存活變異體通過設計新的測試用例可以轉化成可殺除變異體, 剩余的可存活變異體則可能是等價變異體。本文對等價變異體定義如下。
定義 6 (等價變異體)若變異體 p′ 與原有程序 p 在語法上存在差異, 但在語義上與 p 保持一致, 則稱p′ 是 p 的等價變異體。
等價變異體實例
1.3 等價變異體檢測
等價變異體檢測是一個不可判定問題,因此需要測試人員借助手工方式予以完成。等價變異體在語法層次上有微小的差別,但是在語義層次上是一致的。有研究人員發現,在生成的大量變異體中,等價變異體所占比例一般介於10%~40%。在等價變異體的檢測上,主要有兩類方法。
1.3.1 等價變異體靜態檢測法
該方法基於如下猜測:源代碼在編譯時借助優化規則可以生成語義等價代碼。
1.3.2 等價變異體動態檢測法
Adamopoulos 等人提出一種基於遺傳算法的協作演化法(即測試用例和變異體同時進行演化)來檢測可能的等價變異體。他們通過設置合理的適應值函數, 確保當變異體是等價變異體時, 該函數可以返回一個很小的適應值。基於該適應值函數, 群體在演化過程中可以有效淘汰部分等價變異體, 同時將那些難以檢測的變異體和檢測能力強的測試用例均保留下來。
2.1 變異體選擇優化
變異體選擇優化策略主要關注如何從生成的大量變異體中選擇出典型變異體。
2.1.1 隨機選擇法
隨機選擇法嘗試從生成的大量變異體中隨機選擇出部分變異體。具體來說, 首先通過執行變異算子生成大量變異體 M ; 然后定義選擇比例 x ; 最后從變異體 M 中隨機選擇出 |M| ´ x% 的變異體, 剩余未被選擇的變異體則被丟棄。
2.1.2 聚類選擇法
具體來說, 首先對被測程序p 應用變異算子生成所有的一階變異體; 然后選擇某一聚類算法根據測試用例的檢測能力對所有變異體進行聚類分析, 使得每個聚類內的變異體可以被相似測試用例檢測到; 最后從每個聚類中選擇出典型變異體, 而其他變異體則被丟棄。
2.1.3 變異算子選擇法
與上述兩類方法不同, 這類方法從變異算子選擇角度出發, 希望在不影響變異評分的前提下, 通過對變異算子進行約簡來大規模縮小變異體數量, 從而減小變異測試和分析開銷。結果表明, 變異算子選擇法相對於隨機選擇法來說並不存在明顯優勢, 隨機選擇法值得研究人員繼續深入研究。
2.1.4 高階變異體優化法
高階變異體優化法基於如下推測:(1)執行一個k 階變異體相當於一次執行 k 個一階變異體;(2) 高階變異體中等價變異體的出現概率較小。實證研究表明, 采用二階變異體可以有效減少50%的測試開銷, 但卻不會顯著降低測
試的有效性。
4 結束語
變異測試作為一種面向軟件缺陷的測試技術,得到國內外研究人員的關注, 並取得了大量研究成果。本文從變異測試原理、 優化和應用 3個角度對已有的研究工作進行了系統總結。雖然目前針對變異測試的研究已經取得了大量
的成果, 但該領域仍存在很多研究點值得關注。可以考慮的研究點包括:
(1)變異測試中仍存在大量開放性問題。例如等價體變異檢測問題, 已有研究工作主要集中於從生成的變異體中識別出等價變異體。在將來的研究工作中可以考慮通過設計變異算子和分析被測程序特征, 提出有效策略, 在變異體生成過程中避免等價變異體的生成。
(2)在變異測試分析優化中, 即變異體的生成、編譯和執行過程中存在很多研究點。例如, 在變異算子選擇中可以考慮將變異算子按照變異體檢測能力進行排序; 借助硬件的發展和多核 CPU的廣泛使用, 深入研究並行變異測試等。
(3)重點關注面向變異測試的測試用例生成技術。已有研究工作大部分關注於變異體的生成技術, 但面向變異測試的測試用例生成研究還在起步階段, 並亟需成熟工具進行支持。可以進一步考慮將動態符號執行法和 SBST進行有效組合, 以提高測試用例的生成效率。
(4)進一步考慮變異測試研究成果與工業界測試流程的結合。目前的研究一般采用對照試驗方式進行有效性評估, 所得結論很難適用於軟件企業的大型軟件產品。其次研究人員提供的原型工具並未考慮與軟件企業目前已有的開發和測試流程緊密結合, 若要讓企業接受學術界的研究成果, 需要進一步提高測試工具的自動化程度, 改善工具用戶界面, 並提高工具的魯棒性。
參考文獻
An Analysis and Survey of the Development of Mutation Testing, IEEE TRANSACTIONS ON SOFTWARE ENGINEERING, VOL. 37, NO. 5, SEPTEMBER/OCTOBER 2011, Yue Jia, Mark Harman