【准则化的思想】控制流覆盖准则

如果说,枚举的思想是最朴素、最自然的测试设计思想,那么准则化的思想,就是我们最熟悉、最常用的测试设计思想。

我们在讨论“测试选择问题”的时候提到过,对整个测试输入空间进行“穷尽”测试经常是不现实的。我们总是要在有限的资源条件下,从测试输入空间中选取最合适的测试用例,来实现“尽可能充分”的测试。

什么叫“尽可能充分”?就是在最大程度上实现“评估质量”和“检出缺陷”这两个目标。那怎么才算“尽可能充分”呢?或者说,选取哪些用例就够了呢?

要回答这个问题,首先需要建立起一种价值观。因为被测对象的质量特性,可能涉及到很多不同的使用场景,也可能隐藏着各种不同的缺陷,我们需要确定哪些使用场景是更重要的,哪些缺陷是更危险的。然后,我们可以把这种价值观进行“准则化”,形成测试选择的标准,也就是所谓的“测试充分准则”。

测试充分准则的作用有两方面:

  ① 一方面,它可以指导测试选择,帮助我们建立测试集。我们按照一个充分准则做测试选择,就意味着我们遵循了这个准则背后的价值观。很多领域都有关于测试、验证、检验的国家标准、国际标准,这些标准实际上就是测试充分准则。我们按照这些标准做测试,如果测试通过了,就代表被测对象达到了标准要求的最低质量水平,或者被测对象中不存在“标准里明令禁止的某些缺陷”。

  ② 测试充分准则另一方面的作用,是作为一把标尺,评估一个已有测试集的充分性。当然,这里所谓的“充分性”,是基于这个准则背后价值观的、相对的充分性。

在软件领域,应用最普遍的准则就是基于结构覆盖的充分准则。在讨论系统思想的时候,我们说过,被测对象是一个系统,由多个元素组成,元素之间有关联关系,于是被测对象有了“结构”。

当然,元素的定义是比较主观的,这取决于我们所关心的问题,以及我们的价值观。拿人类社会来举例,假如我们认为,国际政治问题特别重要,我们可以把人类社会看成是由一个个国家构成的;但如果我们认为人文人权问题更重要,我们会把人类社会看成是由一个个独立的人构成的。

但是无论怎么定义元素,每个元素中都可能隐藏着缺陷。那么,要实现“尽可能充分”的测试,测试集至少应该覆盖了被测对象的所有元素——这就是基于结构覆盖的充分准则的设计思路。

如果覆盖某个元素的一个测试用例执行成功了,对这个用例所覆盖的元素来说,意味着什么?能说明这个元素里没有缺陷吗?显然不能。如果能,那只要测试覆盖了程序里每一行代码,就能证明程序里没有缺陷了。覆盖某元素的一个测试用例执行成功了,只能说明这个元素“没有缺陷”的概率增加了。

如果覆盖某个元素的一个测试用例执行失败了呢?能说明这个元素里一定有缺陷吗?也不能,因为一个用例通常都会覆盖不止一个元素。覆盖某元素的一个测试用例执行失败了,只能说明这个元素中“包含缺陷”的概率增加了​。

概率的变化,其实也是非常有价值的信息。有一个在学术界比较热门的研究方向,叫“基于频谱的缺陷定位技术”,利用的就是这个信息。所谓频谱,其实就是这样一个直方图:

横轴是被测对象里的各个元素,比如程序里的代码行,纵轴是某一行代码被测试用例覆盖的次数,有些用例执行结果是成功的,有些执行结果是失败的。如果一行代码被失败的用例覆盖的次数比较多,说明这行代码里很可能有缺陷。

在软件领域,我们最熟知的基于结构覆盖的充分准则,就是控制流覆盖准则,它的基本想法是:如果被测程序的价值和风险集中在控制逻辑上,并且程序控制流结构中的某些元素从未被任何测试用例执行过,我们对该程序的正确性不会有太大的信心

程序的控制流结构主要有5种,包括顺序型结构、选择型结构、先判断型循环结构、后判断型循环结构、多情况选择型结构。

举个例子。一个求最大公约数的程序:

	public int gcd(int x, int y) {
		while (x > 0 && y > 0) {
			if (x > y) {
				x = x - y;
			} else {
				y = y - x;
			}
		}
		return (x + y);
	}

这是它的流程图:

可以看出,这是一个典型的以控制逻辑为核心的程序,它主要是通过一个循环结构和一个选择结构,来控制计算的过程。

控制流结构里的元素,可以是语句,也可以是语句构成的分支,也可以是分支构成的路径。所以,最常用的控制流覆盖准则就包括:语句覆盖准则、分支覆盖准则、路径覆盖准则。

  ① 语句覆盖准则代表的是最基本的充分性要求,也就是要求测试覆盖程序里的每一行代码,或者说覆盖程序流程图里的所有节点。

  ② 分支覆盖准则的要求相对高一些,它要求覆盖程序里的所有分支,或者说覆盖流程图里所有的边。

  ③ 路径覆盖准则的要求就更高了,它要求覆盖程序里所有分支的各种组合,或者说覆盖流程图里的所有路径。

前已述及,如果我们的测试集满足语句覆盖准则,并且测试通过了,并不能证明被测程序是正确的。那么,如果测试集满足路径覆盖准则呢?

仍然不能。虽然路径覆盖比语句覆盖的充分性要求高得多,但是路径覆盖仍然做不到绝对充分。我们回忆一下分割测试的要求:第一步,按程序路径来划分测试输入空间;第二步,按期望划分测试输入空间;第三步,把第一步和第二步的划分结果做交叉,这样得到的才是同质子空间。基于同质子空间的测试才是枚举测试,才有可能证明程序是正确的。而路径覆盖准则相当于“仅根据程序路径来划分测试输入空间”,得到的子空间并不是“同质子空间”。具体一点说,如果有两组数据触发的是同一条路径,但是他们在期望里却对应着不同的处理方式,那么很有可能一组数据的输出结果是正确的,另外一组数据的输出结果就是错误的​。

  • 25
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值