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
条件组合覆盖:
含义是执行足够的例子,使得每个判定中条件的各种可能组合都至少出现一次
满足“条件组合覆盖”的测试用例一定满足“判定覆盖”、“条件覆盖”和“判定/条件覆盖”