1.白盒測試開展的必要條件:
程序的規格說明及程序清單
規格說明:規格說明是一個對軟件所應滿足的要求,以可驗證的方式作出完全、精確陳述的文件。
-
-
- 功能規格說明----對軟件所應具備的功能作出規定;
- 性能規格說明----對軟件所應具備的性能,如計算精度、響應速度和占用存儲空間的大小等作出規定;
- 接口規格說明----對軟件與其環境之間、軟件各組成部分之間的接口關系作出規定;
- 設計規格說明----對軟件的設計加以說明。典型的內容包括使用的算法、控制邏輯、數據結構、模塊間接口關系,以及輸入-輸出格式等。
-
程序清單:做的一個完整的工程之后,所有編寫的程序代碼,包括主函數,調用函數,子函數等。
2.白盒測試的覆蓋標准
最徹底的白盒測試是覆蓋程序中的每一條路徑,但由於程序中有循環,所以路徑數目極大,無法執行所有的路徑,所以只能希望能盡可能的覆蓋到更多的路徑。
比如上述程序流程圖中有5條路徑,包含了20次循環,如果要對其路徑進行窮舉覆蓋,那么就有5^20(95 367 431 640 625)條路徑,假如每條路徑執行的時間為1毫秒,那么一天24小時不停的執行,則需要大約3024年。可見,完全覆蓋所有的路徑是不可能的。為了衡量測試的覆蓋程度,需要一些標准,常用的標准從低到高分別是:
語句覆蓋:
語句覆蓋是一種較弱的測試標准,含義就是,選擇足夠的測試用例,使得程序中的每一條語句至少能被執行一次。
是最弱的邏輯覆蓋,它必須和其他方法交互使用。
import unittest class TestDemo(unittest.TestCase): def demo(self, A, B, X): if A == 1 and B == 0: X = X / A if A > 2 or X == 1: X = X return X def test_demo_1(self): ''' 使用語句覆蓋測試 方法demo A=1,B=0,X=1 判定A == 1 and B == 0為真,執行 判定A > 2 or X == 1為真,執行 ''' X = self.demo(A=2, B=0, X=1) expected = 1 self.assertEqual(expected, X) if __name__ == '__main__': unittest.main()
判定覆蓋:
判定覆蓋也稱分支覆蓋,含義是,執行足夠的測試用例,使得程序中的每個判定條件的取真分支和取假分支至少評價一次;
只比語句覆蓋強一點,不能完全查出在判斷的條件中存在的錯誤,需要更強的邏輯覆蓋准則去檢驗內部條件;
滿足判定覆蓋的用例一定是滿足語句覆蓋的。
import unittest class TestDemo(unittest.TestCase): def demo(self, A, B, X): # 如果A比B大,且B不等於1,則,X=A除以B if A > B and B != 1: X = A / B # 上述真或假都會執行以下判斷 # 如果A小於2,則X=A+B if A < 2: X = X + A else: X # 返回X return X # 用例:第一個判斷為真、第一判斷為假、第二個判斷為真、第二個判斷為假 # 第一條用例:第一個判斷為真,第二個判斷為假 # 首先滿足第一個判斷條件為真,A>B,且B不等於1 def test_demo_1(self): # 設置A=3,B=2,X=3 X = self.demo(A=3,B=2,X=1.5) self.assertEqual(1.5,X) # 第二條用例:第一個判斷為假,第二個判斷為真 # 不滿足第一個判斷條件,A>B,且B不等於1;同時也滿足了A小於2 # 設置A=1,B=1,X=2 def test_demo_2(self): X = self.demo(A=1,B=1,X=2) self.assertEqual(3,X) if __name__ == "__main__": unittest.main
條件覆蓋:
含義是執行足夠的測試用例,使得程序中每個判斷的每個條件的每個可能值至少執行一次
滿足條件覆蓋不一定滿足判定覆蓋,比如下面的例子,滿足了所有的條件的每個值都執行了一次,但是都沒有執行X=A/B
import unittest class TestDemo(unittest.TestCase): def demo(self, A, B, X): # 如果A比B大,且B不等於1,則,X=A除以B if A > B and B != 1: X = A / B # 上述真或假都會執行以下判斷 # 如果A小於2,則X=A+B if A < 2: X = X + A # 返回X return X # 所有條件,A>B、A<=B、B!=1、B=1、B<2、B>2 # 第一條用例:A<=B、B=1,A<2 def test_demo_1(self): # 設置A=1,B=1,X=2,輸出X=3 X = self.demo(A=1,B=1,X=2) self.assertEqual(3,X) # 第二條用例:A>B、B!=1、A>=2 def test_demo_2(self): # 設置A=3,B=2,X=2,輸出X=1.5 X = self.demo(A=3,B=2,X=2) self.assertEqual(1.5,X) if __name__ == "__main__": unittest.main
判定/條件覆蓋:
含義是執行足夠的用例,使得程序中每個判斷的每個條件的每個可能值都取到且每個判定條件的取真分支、取假分支都各執行一次
從表面上來看,它測試了所有條件的取值。但是事實並非如此。往往某些條件掩蓋了另一些條件。會遺漏某些條件取值錯誤的情況。為徹底地檢查所有條件的取值,需要將判定語句中給出的復合條件表達式進行分解,形成由多個基本判定嵌套的流程圖。
這樣就可以有效地檢查所有的條件是否正確了
import unittest class TestDemo(unittest.TestCase): def demo(self, A, B, X): # 如果A比B大,且B不等於1,則,X=A除以B if A > B and B != 1: X = A / B # 上述真或假都會執行以下判斷 # 如果A小於2,則X=A+B if A < 2: X = X + A # 返回X return X # 所有條件,A>B、A<=B、B=1、B=1、B<2、B>2 # 所有判定:A > B and B != 1 Ture False # A < 2 Ture False # 第一條用例:A<=B、B=1,A<2,A > B and B != 1(False),A<2(True) def test_demo_1(self): # 設置A=1,B=1,X=2,輸出X=3 X = self.demo(A=1,B=1,X=2) self.assertEqual(3,X) # 第二條用例:A>B、B!=1、A>=2,A > B and B != 1(True),A<2(False) def test_demo_2(self): # 設置A=3,B=2,X=1.5,輸出X=1.5 X = self.demo(A=3,B=2,X=1.5) self.assertEqual(1.5,X) if __name__ == "__main__": unittest.main
條件組合覆蓋:
含義是執行足夠的例子,使得每個判定中條件的各種可能組合都至少出現一次
滿足“條件組合覆蓋”的測試用例一定滿足“判定覆蓋”、“條件覆蓋”和“判定/條件覆蓋”