- 軟件測試的藝術(原書第3版)
- (美)Glenford J.Myers Tom Badgett Corey Sandler
- 3503字
- 2021-01-14 16:50:46
4.1 白盒測試
白盒測試關注的是測試用例執行的程度或覆蓋程序邏輯結構(源代碼)的程度。如同我們在本書第2章所看到的,完全的白盒測試是將程序中每條路徑都執行到,然而對一個帶有循環的程序來說,完全的路徑測試并不切合實際。
邏輯覆蓋測試
如果完全從路徑測試中跳出來看,那么有價值的目標似乎就是將程序中的每條語句至少執行一次。遺憾的是,這恰是合理的白盒測試中較弱的準則。圖4-1描述了這種思想。假設圖4-1代表了一個將要進行測試的小程序,其等價的Java代碼段如下:
通過編寫單個的測試用例遍歷程序路徑ace,可以執行到每一條語句。也就是說,通過在點a處設置A=2,B=0,X=3,每條語句將被執行一次(實際上,X可被賦任何值)。
遺憾的是,這個準則相當不足。舉例來說,也許第一個判斷應是“或”,而不是“與”。如果這樣,這個錯誤就會發現不到。另外,可能第二個判斷應該寫成“X>0”,這個錯誤也不會被發現。還有,程序中存在一條X未發生改變的路徑(路徑abd),如果這是個錯誤,它也不會被發現。換句話說,語句覆蓋這條準則有很大的不足,以至于它通常沒有什么用處。
判定覆蓋或分支覆蓋是較強一些的邏輯覆蓋準則。該準則要求必須編寫足夠的測試用例,使得每一個判斷都至少有一個為真和為假的輸出結果。換句話說,也就是每條分支路徑都必須至少遍歷一次。分支或判定語句的例子包括switch、do-while和if-else語句。在一些程序語言如FORTRAN中,多重選擇GOTO語句也是合法的。
判定覆蓋通常可以滿足語句覆蓋。由于每條語句都是在要么從分支語句開始,要么從程序入口點開始的某條子路徑上,如果每條分支路徑都被執行到了,那么每條語句也應該被執行到了。但是,仍然還有至少三種例外情況:
·程序中不存在判斷。
·程序或子程序/方法有著多重入口點。只有從程序的特定入口點進入時,某條特定的語句才能執行到。
·在ON單元(ON-unit)里的語句。遍歷每條分支路徑并不一定能確保所有的ON單元都能執行到。
由于我們將語句覆蓋視為一個必要條件,那么,作為似乎更佳準則的判定覆蓋的定義理應涵蓋語句覆蓋。因此,判定覆蓋要求每個判斷都必須有“是”和“否”的結果,并且每條語句都至少被執行一次。換一種更簡單的表達方式,即每個判斷都必須有“是”和“否”的結果,而且每個入口點(包括ON單元)都必須至少被調用一次。
我們的探討僅針對有兩個選擇的判斷或分支,當程序中包含有多重選擇的判斷時,判定/分支覆蓋準則的定義就必須有所改變。典型的例子有包含select(case)語句的Java程序,包含算術(三重選擇)IF語句、計算或算術GOTO語句的FORTRAN程序,以及包含可選GOTO語句或GO-TO-DEPENDING-ON語句的COBOL程序。對于這些程序,判定/分支覆蓋準則將所有判斷的每個可能結果都至少執行一次,以及將程序或子程序的每個入口點都至少執行一次。
在圖4-1中,兩個涵蓋了路徑ace和abd,或涵蓋了路徑acd和abe的測試用例就可以滿足判定覆蓋的要求。如果我們選擇了后一種情況,兩個測試用例的輸入是A=3,B=0,X=3和A=2,B=1,X=1。
判定覆蓋是一種比語句覆蓋更強的準則,但仍然相當不足。舉例來說,我們僅有50%的可能性遍歷到那條X未發生變化的路徑(也即,僅當我們選擇前一種情況)。如果第二個判斷存在錯誤(例如把X>1寫成了X<1),那么前面例子中的兩個測試用例都無法找出這個錯誤。
比判定覆蓋更強一些的準則是條件覆蓋。在條件覆蓋情況下,要編寫足夠的測試用例以確保將一個判斷中的每個條件的所有可能的結果至少執行一次。因為,就如同判定覆蓋的情況一樣,這并不總是能讓每條語句都執行到,因此作為對這條準則的補充就是對程序或子程序,包括ON單元的每一個入口點都至少調用一次。舉例來說,分支語句包含兩種情況:K是否小于或等于50?以及J+K是否小于QUEST?因此,需要針對K<=50、K>50(達到循環的最后一次迭代)以及J+K<QUEST、J+K>=QUEST的情況設計測試用例。
圖4-1有四個條件:A>1、B=0、A=2以及X>1。因此需要足夠的測試用例,使得在點a處出現A>1、A<=1、B=0及B<>0的情況,在點b處出現A=2、A<>2、X>1及X<=1的情況。有足夠數量的測試用例滿足此準則,用例及其遍歷的路徑如下所示:
請注意,盡管在本例中生成的測試用例數量是一樣的,但條件覆蓋通常還是要比判定覆蓋更強一些。因為,條件覆蓋可能(但并不總是這樣)會使判斷中的各個條件都取到兩個結果(“真”和“假”),而判定覆蓋卻做不到這一點。舉例來說,在相同的分支語句中,存在一個兩重分支(執行循環體,或者跳過循環體)。如果使用的是判定覆蓋測試,將循環從K=0執行到K=51即可滿足該準則,但從未考慮到WHILE子句為假的情況。如果使用的是條件覆蓋準則,就需要設計一個測試用例為J+K<QUEST產生一個為假的結果。
雖然條件覆蓋準則乍看上去似乎滿足了判定覆蓋準則,但并不總是如此。如果正在測試判斷條件IF(A&B),條件覆蓋準則將要求編寫兩個測試用例:A為真,B為假;A為假,B為真。但是這并不能使IF語句中的THEN被執行到。對圖4-1所示例子所進行的條件覆蓋測試涵蓋了全部判斷結果,但這僅僅是偶然情況。舉例來說,兩個可選的測試用例:
涵蓋了全部的條件結果,卻僅涵蓋了四個判斷結果中的兩個(這兩個測試用例都涵蓋到了路徑abe,因而不會執行第一個判斷結果為真的路徑,以及第二個判斷結果為假的路徑)。
顯然,解決上面左右為難局面的辦法就是所謂的判定/條件覆蓋準則。這種準則要求設計出充足的測試用例,將一個判斷中的每個條件的所有可能的結果至少執行一次,將每個判斷的所有可能的結果至少執行一次,將每個入口點都至少調用一次。
判定/條件覆蓋準則的一個缺點是盡管看上去所有條件的所有結果似乎都執行到了,但由于有些特定的條件會屏蔽掉其他的條件,常常并不能全部都執行到。請參見圖4-2來觀察此種情況。圖4-2中的流程圖描述的是編譯器將圖4-1中的程序編譯生成機器代碼的過程。源程序中的多重條件判斷被分解成單個的判斷和分支,因為大多數的機器都沒有能執行多重條件判斷的單獨指令。那么,更為完全的測試覆蓋似乎是將每個基本判斷的全部可能的結果都執行到,而前兩個判定覆蓋的測試用例都做不到這點;它們未能執行到判斷H中的結果為“假”的分支,以及判斷K中結果為“真”的分支。
如圖4-2所示,其中的原因是“與”和“或”表達式中某些條件的結果可能會屏蔽掉或阻礙其他條件的判斷。舉例來說,如果“與”表達式中有個條件為“假”,那么就無須計算該表達式中的后續條件。同樣,如果“或”表達式中有個條件為“真”,那么后續條件也無須計算。因此,條件覆蓋或判定/條件覆蓋準則不一定會發現邏輯表達式中的錯誤。
所謂的多重條件覆蓋準則能夠部分解決這個問題。該準則要求編寫足夠多的測試用例,將每個判定中的所有可能的條件結果的組合,以及所有的入口點都至少執行一次。舉例來說,考慮下面的偽代碼程序:
要測試四種情況:
1.I<=TABSIZE,并且NOTFOUND為真;
2.I<=TABSIZE,并且NOTFOUND為假(在到達表格尾部前查詢指定條目);
3.I>TABSIZE,并且NOTFOUND為真(查詢了整個表格,未找到指定條目);
4.I>TABSIZE,并且NOTFOUND為假(指定條目位于表格的最后位置)。
很容易發現,滿足多重條件覆蓋準則的測試用例集,同樣滿足判定覆蓋準則、條件覆蓋準則以及判定/條件覆蓋準則。
再次回到圖4-1中,測試用例必須覆蓋以下8種組合:
1.A>1,B=0 5.A=2,X>1
2.A>1,B<>0 6.A=2,X<=1
3.A<=1,B=0 7.A<>2,X>1
4.A<=1,B<>0 8.A<>2,X<=1
注意,與左邊的情況一樣,第5至第8組合表示了第二個if語句的值。由于x可能在該if語句之前發生了改變,因此這個if語句所需的值必需對程序邏輯進行回溯,以找到相對應的輸入值。
要測試的這8種組合并不一定意味著需要設計出8個測試用例。實際上,用4個測試用例就可以覆蓋它們。下面是這些測試用例的輸入,以及它們覆蓋的組合:
A=2,B=0,X=4 覆蓋組合1,5
A=2,B=1,X=1 覆蓋組合2,6
A=1,B=0,X=2 覆蓋組合3,7
A=1,B=1,X=1 覆蓋組合4,8
圖4-1的程序存在4條不同的路徑,需要4個測試用例,這樣的情況純屬巧合。事實上,這4個用例也沒有覆蓋到每條路徑,路徑acd就被遺漏掉了。舉例來說,對于如下所示的判斷語句,盡管它只包含兩條路徑,仍可能需要8個測試用例:
在存在循環的情況下,多重條件覆蓋準則所需要的測試用例的數量通常會遠遠小于其路徑的數量。
總的來說,對于包含每個判斷只存在一種條件的程序,最簡單的測試準則就是設計出足夠數量的測試用例,實現:(1)將每個判斷的所有結果都至少執行一次;(2)將所有的程序入口(例如入口點或ON單元)都至少調用一次,以確保全部的語句都至少執行一次。而對于包含多重條件判斷的程序,最簡單的測試準則是設計出足夠數量的測試用例,將每個判斷的所有可能的條件結果的組合,以及所有的入口點都至少執行一次(加入“可能”二字,是因為有些組合情況難以生成)。
- FreeSWITCH 1.8
- Java面向對象思想與程序設計
- Pandas Cookbook
- Mastering Articulate Storyline
- DevOps入門與實踐
- Internet of Things with Intel Galileo
- Bootstrap Essentials
- Banana Pi Cookbook
- Apache Karaf Cookbook
- Python時間序列預測
- 響應式Web設計:HTML5和CSS3實戰(第2版)
- UI設計全書(全彩)
- 動手打造深度學習框架
- Unity Android Game Development by Example Beginner's Guide
- MySQL 8從零開始學(視頻教學版)