控制流測試與條件測試


控制流測試

控制流測試(Control Flow Testing):是一種在考慮測試對象的控制流情況下導出測試用例的測試方法,並且借助於控制流圖能評估測試的完整性(覆蓋率)。

原則

  • 控制流圖是一個帶有開始節點和結束節點的有向圖
  • 程序的指令(語句)是通過節點來表示的
  • 一個不帶分支和匯總的語句序列可以簡單地用一個節點來表示
  • 語句之間的路徑通過有向線(控制流)表示
  • 控制流圖的開始和結束節點在實際應用中常常被省略

測試活動

  1. 列出應該覆蓋的路徑
  2. 設計輸入、輸出使得程序能按邏輯含義走到此路徑
  3. 運行測試來觀察此路徑是否走到。如果沒有走到,則要么是對邏輯理解不足,要么是邏輯本身有錯誤。

主要的控制流測試方法:

  • 語句覆蓋
  • 分支覆蓋
  • 判定覆蓋
  • 路徑覆蓋(包括結構化的路徑覆蓋等)

語句覆蓋

語句覆蓋(C0-覆蓋) / 語句覆蓋測試 / 語句測試(Statement testing):在控制流中每條可執行的語句至少被執行一次!

  • 必要的、最簡單的,但也是最弱的標准
  • 無法檢測到缺失的語句
  • 但能發現無法執行到的語句(死代碼)

覆蓋率:
語句覆蓋 = 已執行的語句數目 / 所有語句的總數目 * 100%

語句即節點,控制流圖內的所有節點都走到即為100%語句覆蓋

分支覆蓋

分支覆蓋(C1-覆蓋) / 分支覆蓋測試 / 分支測試(Branch testing):在控制流圖內的每一條邊都至少被執行一次!

  • 在實踐中作為最小的測試標准
  • 能發現無法執行到的程序分支
  • 無法發現缺失的分支
  • 沒有測試到分支的組合

覆蓋率:
分支覆蓋 = 已執行的分支數目 / 分支總數目 * 100%

每一條邊即每一條控制流(有向線)都走過了,才為100%分支覆蓋

判定覆蓋

判定覆蓋 / 判定測試(Decision testing):每一個可能的判定輸出都應該被測試到!

  • 如果達到100%判定覆蓋,則等價於分支覆蓋
  • 但這里計數的不是分支,而是判定的輸出,判定覆蓋在小於100%時,判定的覆蓋率與分支的覆蓋率可能有所不同!

覆蓋率:
判定覆蓋 = 已執行的判定結果 / 所有的判定結果總數 * 100%

判定覆蓋計數的是判定的結果,即布爾值truefalse的個數

示例代碼:

if (x > y) {
    y = x;
}
if (y > z) {
    z = y;
}

這段代碼一共有兩個if判定,每個判定都可以有truefalse兩個判定結果,一共是四個判定結果。

所以如果只用一條case同時覆蓋x > yy > z,實際上執行到的是兩個判定結果,判定覆蓋率為2 / 4 = 50%

在同一條case的情況下,畫出控制流圖,分支覆蓋一共有9條有向線(包括開始節點和結束節點的兩條有向線),有兩條分支沒有走到,所以分支覆蓋率為7 / 9 = 77.8%

路徑覆蓋

路徑覆蓋(C-覆蓋,C4-覆蓋)/ 路徑覆蓋測試 / 路徑測試(Path testing):在控制流圖內的每一個分支序列(路徑)都應該執行一次!

強標准,因為

  • 在包含循環時,可能會有無數的路徑
  • 在具有k個連續的分支時,則會有2k種不同的路徑

定制選擇有意義的路徑(Beizer)
限制重復次數:循環覆蓋測試方法
限制考慮的路徑:片段對覆蓋(Segment pair)

針對路徑測試,按照Beizer的啟發式方法[Beizer90]:

  • 從最簡單的、功能上有意義的路徑開始(從入口到出口的最簡單路徑)
  • 每次新的路徑應該只是對現有的微小變化(如果可能,僅只改變一個判定輸出/真值)
  • 優先考慮短的路徑、簡單路徑、功能上有意義的路徑、不帶循環的路徑
  • 應該達到100%判定覆蓋
  • 避免功能上無意義的路徑,如果為了達到判定覆蓋必須執行這路徑,則應該檢查是否是一個錯誤,如果不是,則增加此路徑。
  • 優先考慮那些很有可能是實際執行的路徑

從開始節點到結束節點之間全部可能的路徑都走過才是100%路徑覆蓋

  • 部分路徑測試經常用在安全關鍵軟件的測試中
  • 常用條件覆蓋方法組合使用,因為它們檢查軟件的另一個方面
  • 當只需要增加少量的測試用例時,它可以作為分支測試的深入
  • 應該使用工具來創建控制流圖

結構化的路徑覆蓋

結構化的路徑覆蓋(Ci(k)-覆蓋):執行在一個內循環中運行次數還沒有超過k次的所有路徑!

對於k = 2時,這種方法也成為內部邊界-路徑覆蓋(Boundary Interior)

僅僅當k為很小值時才有實際意義。

其他針對循環的測試的標准:

  • 最小和最大迭代次數,排除迭代數
  • 在程序中的循環一般:嵌套、交叉、非結構化的循環

條件測試

  • 簡單條件測試
  • 條件測試/判定測試 或 判定條件測試
  • 改進的條件/判定測試(MC/DC)
  • 復合條件測試

它們的區別是測試的深度(從上往下越來越深入),需要的測試用例數,以及能發現多少缺陷

簡單條件測試

簡單條件測試(Condition testing:一個布爾表達式內的每個原子條件(Atomic condition) 都應該對其二個值(真/TRUE 和 假/FALSE)進行測試。

一個原子條件是一個不包含邏輯運算符NOT、AND或OR的條件

如果在程序內的所有條件都僅僅是一個原子條件,則相應的簡單條件測試對應為判定測試。

滿足簡單條件覆蓋不一定會滿足判定覆蓋,所以簡單條件測試僅僅是理論上進行探討,沒有太大實際意義

條件測試/判定測試 或 判定條件測試

**條件測試/判定測試(Decision condition testing):

  • 每一個判定都應該要對它的二個值(真和假)進行測試
  • 每個原子條件都應該要對它的二個值(真和假)進行測試

包含了簡單條件覆蓋以及判定覆蓋。通常不需要比簡單條件覆蓋更多的測試用例,但是必須謹慎選擇。

  • 此方法適合於測試那些重要的,但還不是關鍵和核心的代碼
  • 此方法與后面的二種方法相比需要較少的測試用例,但是比單純的判定覆蓋要更繁瑣(還要看原子條件的覆蓋)

改進的條件/判定測試(MC/DC測試)

改進的條件/判定測試(Modified Condition/Decision Coverage)

  • 每一個判定都應該要對它的二個真值(真和假)進行測試
  • 每一個原子條件都應該對它的二個真值(真和假)進行測試
  • 在測試中能夠表明,每一個原子條件的值獨立地影響表達式的結果

針對單個的原子條件,必須關注具有不同結果的測試用例,結對進行比較。

  1. 先列出所有可能的真值組合
  2. 選出那些單個原子條件影響結果的測試用例對
  • 提供一個更高的控制流覆蓋並能發現比條件覆蓋/判定覆蓋更多的缺陷
  • 需要更多的測試用例,但是:
    • 當有n個原子條件,通常需要n+1個測試用例。測試用例的數目與條件的數目是線性關系(線性增長)。
    • 很適合安全關鍵系統,例如,在航空和航天業廣泛采用改進的條件測試/判定測出(MC/DC)方法

限制:耦合的條件

例如: (A AND B) OR ((NOT A) AND C)

這些條件稱作耦合(重疊),而這些耦合的項往往無法實現MC/DC測試。

解決方法:

  • MC/DC僅僅針對不耦合的條件
  • 對於含有耦合條件的每個判定作為特例,視不同的情況生成測試用例

限制:短路/精簡的評判(Short-circuiting)

在有條件的進行評價的程序設計語言中往往無法達到MC/DC的覆蓋。

解決方法:必須降低“測試用例對”的要求,對於每個原子條件生成一對測試用例,

  • 要覆蓋這個條件的二個真值(真/假)
  • 要覆蓋整個判定式的二個真值(真/假)
  • 所有其他原子條件具有相同的邏輯或不進行評估。

復合條件測試

復合條件測試(Multiple condition testing):測試原子條件的所有可能的真值(真/假)組合

  • 復合條件覆蓋包含了MC/DC覆蓋
  • 因為測試用例可以從真值表直接導出,所以測試的設計更為簡單
  • 缺點:非常耗資(n個原子條件將會有2n個組合)
  • 長期需要穩定可靠的嵌入式系統測試中常會使用此方法(例如,在電話網內的交換機系統,按要求應該運行30年),但也逐漸被MC/DC所替代


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM