1. 程式人生 > >並行測試和變異測試三篇文獻總結(二)

並行測試和變異測試三篇文獻總結(二)

A Path Coverage-Based Reduction of Test Cases and Execution Time Using Parallel Execution

基於路徑覆蓋的並行執行減少測試用例和執行時間

© Springer Nature Singapore Pte Ltd. 2019 M. N. Hoda et al. (eds.), Software Engineering, Advances in Intelligent Systems and Computing

在本文中,生成一組測試,每個測試遍歷指定的路徑。 目的是確保程式碼中沒有任何路徑不被覆蓋。 對於這些路徑,生成大量測試資料是非常繁瑣的任務。 結果,應該應用某種策略來減少大量冗餘的測試用例的數量,即重複的同一組測試用例。 通過應用策略來避免衝突,將超出測試路徑生成以減少冗餘並生成有效的測試用例以覆蓋控制流圖中的所有路徑。

現有技術的潛在缺點是它們僅覆蓋了一條單一路徑。

演算法的過程:

1.使用原始碼(對於確定三個給定整數f,s和t 的中間值的程式),繪製問題的相應控制流圖

2.然後,從圖(流圖)確定圈複雜度

3.之後,確定線性獨立路徑的基組。

4.然後,使用ReduceDomains演算法減少每個輸入變數的域。

5.在生成測試套件之後,通過使用代數條件將特定值分配給變數並檢查覆蓋標準,判斷是否滿足。

6.應用並行測試用例執行器,以減少大量冗餘的測試用例。

控制流圖的描述資訊:

在這裡插入圖片描述

每一個狀態由一個節點表示,每一個邊表示狀態的轉移。圈複雜度用於確定來自流圖的線性獨立路徑的數量,它是獲得最大程式碼覆蓋率所需的測試集總數的標誌,隨後的測試集提供了比語句和分支覆蓋更深入的測試,

V (G)=e − n +2 p,e和n是控制流圖中邊的總數和節點總數,p是圖的連線元件數目(圖的元件數是相連節點的最大集合)。控制流圖都是連通的,所以p=1。V(G)的值是程式中所有可能執行路徑的標誌,表示完全測試方法所需的測試用例數量的下界。

在這裡插入圖片描述

在這裡插入圖片描述

在這裡插入圖片描述

由於每個獨立的路徑都是通過執行緒並行執行的,所以它包含了測試用例的所有組合。

圈複雜度詳解:

其他計算圈複雜度的方法:

計算公式2:V(G)=區域數=判定節點數+1。其實,圈複雜度的計算還有更直觀的方法,因為圈複雜度所反映的是“判定條件”的數量,所以圈複雜度實際上就是等於判定節點的數量再加上1,也即控制流圖的區域數。

對於多分支的CASE結構或IF-ELSEIF-ELSE結構,統計判定節點的個數時需要特別注意一點,要求必須統計全部實際的判定節點數,也即每個ELSEIF語句,以及每個CASE語句,都應該算為一個判定節點。

計算公式3:V(G)=R。其中R代表平面被控制流圖劃分成的區域數。

適用場景:

針對程式的控制流圖計算圈複雜度V(G)時,最好還是採用第一個公式,也即V(G)=e-n+2;而針對模組的控制流圖時,可以直接統計判定節點數,這樣更為簡單;針對複雜的控制流圖是,使用區域計算公式V(G)=R更為簡單。

路徑覆蓋:

路徑覆蓋是指選取足夠多的測試資料,使程式的每條可能路徑都至少執行一次(如果程式圖中有環,則要求每個環至少經過一次)。路徑覆蓋是覆蓋率最高的一種覆蓋技術。

路徑覆蓋率的公式:路徑覆蓋率=被執行到的路徑數/程式中總的路徑數。

獨立路徑數的計算:

第一步,從流圖中找出程式所有的必經節點(流圖中任何獨立路徑都必定經過的節點叫做必經節點),記作IV(i),其中i為整數且。

第二步,從流圖中找出從必經節點N(i)到必經節點N(i+1)的獨立路徑數W(i),其中i為整數且0 \le i<N

第三步,重複上一步,直到程式結尾。

第四步,根據乘法法則,獨立路徑數= W(i),其中i為整數且0 \le i < N,即獨立路徑數=W(0) * W(1) * ⋯ * W(N一1)。

完全路徑是指所有獨立路徑的集合,非完全路徑就是所有獨立路徑集合的真子集。由於程式中可能會包含有多個條件的判定,所以程式流程圖可能包含有隱含路徑,從而有程式流圖轉換成的對應流圖可能包含有隱藏路徑。

消除隱含路徑的辦法就是將含有多個條件的判定分為多個判定。

完全路徑覆蓋的具體步驟:

1、將判定語句的條件進行分離,細化程式流程圖,使其不含隱含路徑。

2、根據程式流程圖畫出流圖,找出必經節點,必經節點數為N。

3、將程式流程圖在必經節點處割斷,將整個程式分解為N+1個程式片斷。

4、找出程式片斷i的完全路徑,為程式片斷i的每條獨立路徑設計用例,其中:1 \le i \le N+l

5、結合所設計的測試用例,將程式片斷i的引數初始化,其中1 \le i \le N+1

6、將測試用例付諸測試,重複第四步至第六步,直到i=N+1。

Coverall algorithm覆蓋演算法

A path-aware approach to mutant reduction in mutation testing

Information and Software Technology

Chang-ai Sun ,Feifei Xue, Huai Liu ,Xiangyu Zhang

減少變異體的數量來減少測試代價。定義了兩個path-aware啟發式規則:分別名為模組深度和迴圈深度規則,並且結合基於狀態和變異運算元選擇提出四種變異體選擇策略。與隨機變異體選擇策略相比,有更高的有效性。

在這裡插入圖片描述

我們應該對變異體給予更高的優先順序,因為變異體的相關缺陷位於較深的位置。

減少變異體數量的一些前期工作:

1.random mutant selection(可能會丟棄一些很難被殺死的變異體)

2.operator-based mutant selection

一些定義:

m->n 模組m呼叫模組n

Callers(m)={x|x->m}模組m直接呼叫者的集合。

MD(mi_i):mi_i基於所有模組呼叫關係的模組深度

在這裡插入圖片描述

在這裡插入圖片描述

LD(bi_i)迴圈/分支深度

在這裡插入圖片描述
路徑感知減少變異體的方法:
在這裡插入圖片描述
Depth:變異體的相關缺陷位於較深的位置

Diversity:選擇變異體的多樣性由不同的啟發式規則獲得

傳統變異分析 T=<P,S,D,L,A>

本文的方法中:

E=<P,S,D,L,A,Pr_r>

Pr_r是Ai_i中每一個可替代ai,j_{i,j}發生的可能性

L=<Loc,MD,LD>

啟發式規則:

**module depth,loop/branch depth,**statement selection,Operator selection

減少變異體的策略:

md-ld-op,ld-md-op表現最好,

stm-ld-md,op-ld-md非path-qware技術

實驗步驟:

a.選擇與所有非等價變異體相關的目標程式Muall_{all}

b.取0到100的實數x,變異體的抽樣比x%。

c.應用一個變異體減少策略選擇x%以獲得變異體子集Mureduced_{reduced}

d.使用隨機測試技術構建測試套件,在目標程式的測試池中隨機選擇測試用例直到所有Mureduced_{reduced}中的變異體被殺死。

e.應用TS去測試Muall_{all}中所有的變異體並且計算變異評分MSall_{all}

未來工作:

1.發現更多的啟發式規則並且設計更多的精確減少策略。

2.構建在大型系統中評估路徑感知方法有效性和應用的方法,不同領域的應用。

文獻:

[28]對於單元和整合測試選擇部分變異運算元,這個方法可以有效減少變異體數量沒有考慮變異評分的危害。

[29]java程式的三種典型的變異運算元,發現已經存在的冗餘變異體可能會影響包括有效性和變異測試的質量,並且也給出了一些移除冗餘變異體的方法。

[30]one-op變異。

[10]隨機變異體選擇等價於基於變異運算元的選擇。

[31]並行變異運算元的選擇可以有效地減少變異體的數量,並且表現勝過隨機選擇。

[32]隨機選擇和基於變異運算元的變異體選擇結合。

[33]高階變異體

[44]檢測等價變異體的技術

優化執行時間的方法:

[19]在編譯器中使用工具減少變異體生成和編譯的時間。

[45]schema-based方法,位元組碼翻譯技術允許變異體直接執行因此可以節省編譯時間

[47]提出一個技術ReMT去提高變異測試有效性通過軟體測試進化過程

[48]提出了另一種技術FaMT最小化和最優化每個變異體的測試用例

[49,50]變異測試工具

[51]變異測試中應用程式路徑,提出了一種基於路徑的測試用例生成方法,在殺死變異體方面是有效的

Selective Mutation Testing for Concurrent Code

併發程式碼的選擇性突變測試
這篇論文關注的併發程式碼是指shared-memory concurrent code.也就是共享記憶體的併發程式碼。
共享記憶體系統的主要特性是:

  • 記憶體對於所有處理器來說是一樣的,例如,所有處理器所對應的相同資料結構都存在於相同的邏輯地址,也就是說可以從相同的記憶體單元中獲得該資料結構。

  • 通過控制處理器對共享記憶體的訪問許可權可以達到同步控制的效果。實際上,每次只有一個處理器擁有對記憶體資源的訪問許可權。

  • 當一個任務正在訪問共享記憶體的時候,其它所有任務都不能改變記憶體單元的內容。

  • 共享記憶體很快,兩個任務通訊的時間和讀取單個記憶體單元的時間相等(取決於記憶體的訪問速度)

在這裡插入圖片描述
選擇性變異:僅使用一部分來減少變異體數量,使得殺死由該子集產生的所有變異體的測試套件也能殺死所有變異運算元產生的所有變異體。

併發bug:資料競爭,原子性違背,死鎖。

選擇變異體子集的兩種方式:

1.selective mutation

2.random selection

比較的方面:

1.**變異體數量:**未選擇的變異體數量/產生的變異體總數

2.**非選擇性變異得分的有效性:**殺死所有選定的非等價變異體的測試套件殺死的所有生成的非等價變異體的百分比。

對於併發程式碼的評估:

1.詳盡的分析了所有可能的變異運算元子集 的cost和effectiveness的權衡。

(用盡可能少的併發運算元,嘗試所有可能變異子集最佳成本效率)

2.比較不同選擇性方法之間的成本。

(突變體的數量,併發測試的勘探成本)

3.評估順序程式和併發程式的變異運算元是獨立的還是相互包含的。

併發測試套件可以獲得對於順序執行程式來說高變異分數

本文提出了三種新的變異運算元:RTS,MTS,WTIS

RTS:刪除Thread物件上start方法的呼叫。

MTS:在Thread物件上移動start方法的呼叫。

RTS和MTS產生的變異體可能會導致程式死鎖。

WTIS:在同步塊內將while替換成if,可能會導致原子性違背。

插入變異體的方法:

1.建立SUT的多個拷貝並在每個拷貝中插入一個變異體,從而產生與變異體一樣多的拷貝。

2.使用變異模式:為所有變異體僅建立SUT的一個變異版本,使得全域性ID指定啟用哪個變異體。

並行測試與順序執行程式之間的測試的一個顯著差異在於並行測試依賴於執行緒排程。

難點:給定併發程式,測試和變異體,有必要執行原始程式和變異體所有可能的程序以確定變異體是否被殺死。

false negative:變異程式碼中從未執行導致不同輸出的排程,則可能無法檢測變異體被殺死。

false positive:變異程式碼上獲得的輸出與原始程式碼上獲得的輸出不同,則可能會報告變異體被殺死。

研究中提出9個問題,分別是:

1.併發程式碼中最主要的變異運算元是什麼?

Answer:RSK是併發程式碼中最主要的變異操作符,其次是MSP和RSB。

2.n-選擇性變異是否適用於併發程式碼的變異測試?

不同於選擇性突變序列變異運算元,n-selective突變測試(n∈{ 2 4 6 })並不適用於突變測試併發突變運算元。

3.哪一類的變異運算元能夠獲得最高的(非選擇性的)變異分數?

“修改關鍵字”(MK)類別是最有效的。然而,與順序程式變異運算元不同的是,沒有一個類別能夠獲得足夠的分數。

4.獲得高(非選擇性)突變分數和顯著節省(就突變體數量而言)的變異運算元集是什麼?

{MSP, RSK, RTXC, SHCR, SKCR, SPCR, WTIS}是在充分突變得分(99.67%)的情況下達到最高節約(46.37%)的集合。

5.對於(非選擇性)變異分數的不同值,可以實現的最大節省是什麼?

圖1顯示了每個突變值的最大節省。如果得分超過95%,則可節省40%至50%。如果節省超過90%,分數約為60%。

6.在未來的研究中,哪組併發變異運算元為使用提供了良好的權衡?
在這裡插入圖片描述

7.如何比較基於操作符和隨機變異運算元的併發變異運算元?

對於併發變異運算元,基於操作符的突變選擇要比隨機選擇好一點。

8.突變體數量上的節約和勘探成本上的節約有什麼關係?

從突變體數量上的節省對應於從併發程式碼的探索成本上的節省。

9.併發和順序突變操作符是獨立的,即沒有一個能包含另一個?

併發和順序變異運算元是獨立的。兩者均不包含,說明了併發變異運算元研究的重要性

實驗所研究的程式:
在這裡插入圖片描述

三個(大)程式來自真實世界的開放原始碼:Guava[21]是一個谷歌專案,包括併發集合和併發庫;Lucene[32]是一個實現併發文字搜尋引擎的Apache專案;而Pool[46]是一個Apache專案,它提供了併發的物件池API。

小程式是由併發構造實現的。

變異體的產生:

選擇性突變是多執行緒程式碼的理想選擇。

併發突變運算元生成的突變體分佈高度不均勻。

測試元件:

變異體執行:

(1)壓力測試只是在常規JVM上執行原始的或突變的SUT(不需要進一步修改)。

(2) Java PathFinder (JPF)[52]是一個明確的模型檢查器,實現為一個特殊的JVM,可以探索所有可能的時間表;它還支援有限數量的執行緒搶佔。

殺死變異體:

(1)選擇一個突變運算元子集;

(2)為所選擇的突變運算元生成的突變體找到合適的測試套件;

(3)測量測試套件對所有突變運算元的非選擇性突變得分。

選擇性變異的結果:
測試套件(Test Suites)之前的研究是通過生成大量的測試套件來消除一個測試套件的潛在偏差,並平均所有結果。而測試套件更適用於序列程式碼,因為序列程式碼可以生成巨大的測試池。
為了更加精確,在收集資料開銷-有效時,採用以下三步:

  1. 選擇變異運算元子集。

  2. 尋找一個合適的測試套件,針對選擇的變異運算元產生的變異運算元集。尋找一個合適的測試套件,針對選擇的變異運算元產生的變異運算元集。

  3. 衡量通過關於所有的變異運算元測試套件獲得的非選擇性變異評分。

未來的工作就是通過實驗發現更多的在新的並行結構中的變異運算元。
相關工作:
一些變異工具的介紹:MuJava;Jumble是工業級的變異測試工具,並且更關注有效性;ConMAn實現了併發變異運算元集;Javalanche適用於選擇性變異的工具。
如果大家也在研究關於選擇性變異方向或者併發程式碼變異測試或者平行計算方向歡迎給我留言,我們可以一起交流喲~