我经常被问到这个问题:“如何衡量测试的有效性?”或者是“如何评价测试的有效性?” 仿佛只要我说出个一二三来,听者根据这套规则,可以得到一个结论:“我们的测试是否是有效的?”

  很多团队都会定义一些自己的规则,这些规则几乎包罗万象了,比如通过覆盖率的数据、比如通过bug的数量和趋势、比如通过测试用例的评审、比如通过测试策略的评审等等。可是似乎,多少年来,鲜有某个团队可以自信的说:“我的测试是充分的”或者说“我的测试还有哪些不够充分,其他都是充分的了”。

  评价测试的有效性离不开开发的实现及项目的上下文

  大师Gerald M. W.的话总是能给人顿悟的感觉,他的著作《Perfect software》里对这个问题进行了逆向论述:

  你如何分辨测试的好与坏?首先不妨先定义一下什么是“好的测试”。

  理想情况下,一套“完美”的测试应该满足以下特点:

  a、它能够检测到系统中的每一个bug;

  b、它不会误把任何一个正当的实现判做bug;

  c、通过运行这些测试我们完全相信它能够做到a和b;

  d、它能不费时地、以不是很昂贵的代价完成上述a、b、c。

  假如真的有一套完美的系统,没有bug的系统。我们有两套测试集,一套不是那么充分、一套比较充分。如果用来测试该完美的系统,两套测试集都没有发现bug。它们都能满足上述四条,那么它们都是完美的吗?

  实际上,我们无法预知一个系统是否是完美无bug的系统,从而也无法知道是否这两套测试集都满足上述条件。

  这个例子告诉我们,测试从天生不是独立存在的,测试和开发密不可分。说一个测试好与坏,也不能离开开发的实现以及项目的上下文。所以,这个“好”是相对的。对于这个实现,这个测试是好的。换一种实现,同样的测试集可能不是好的了。

  如何证明测试是“有效的”或“无效的”?

  那么,我们怎样知道相对于我们自己的项目实现和上下文,我们现有的测试是不是好的呢?<Perfect Software>里也谈到一些做法:

  - 我们可以通过事后评估的方式。比如软件发布半年后的缺陷数给我们一个事实的依据,用以判断之前的测试的好坏。你知道我们的测试遗漏了那种bug,以后如何改进。当然,这个判别也不是一定准确的,有可能,发布10年后,软件有个致命的bug才暴露出来,而我们显然不能等待如此漫长的时间才来评判。

  - 我们可以故意的植入缺陷,然后根据实际发现的比率来预知软件还有多少bug没有发现出来,从而判别测试的好坏。当然,这种方法和你植入缺陷的技巧密不可分了,也不是的准确。

  - 当然,我们可以做测试估计,根据缺陷趋势估计还剩下多少bug。估算总是不准确的。

  难道我们没有办法准确地判别测试是不是“好”的了吗?很不幸,答案是“是的”。

  但是我们可以做的事情是,通过问一系列问题,判别一个测试是不是“不好”的。这像软件测试本身一样,我可能没有办法证明一个功能是可用的(你只能证明你运行过的测试用例是passed,而你只运行了其中很小很小的一部分用例),但是很容易证明一个功能是不可用的,我只要找到一种情况,运行失败可以了。

  - 测试是否能够提供所需要的信息?如果不是,很显然不是好的测试。

  - 测试是否进行了必要的文档记录?如果没有,测试过程和结果是否可信?如果不是,很显然不是好的测试。

  - 重要的部分是否进行了测试覆盖?如果没有,很显然也不是好的测试。

  - 趋势和状态是否过于简单和规则化了?那么测试有可能过于表面化了,不够深入。

  - 管理者是否清晰测试状态?如果他们只通过报告文档来知晓测试的状态,很可能某些测试数据是为了迎合管理者的。

  ......

  所以你看,证伪要比证实容易得多,如果你想方设法证实自己的测试是有效的,不如从“使得测试看起来不那么有效”的几个方面入手,审视测试的中间过程,同时不要脱离开发实现和项目上下文,发现“测试的坏味道”及时治理,消除各方对测试的疑虑。

  如果有人问你,如何衡量一个人是否幸福?你是否会拿出一个checklist对照检查,如果都满足,判定此人是幸福的?这样判别的结果与真实的结果总是完全一致吗?你更关心表面上的、客观的判决结果呢(例如城市幸福指数)?还是更关心一个人心理的、主观的幸福感呢?其实,幸福是一种感觉,很难通过几个指标准确衡量。测试的有效性也很难通过有限的几个指标可以衡量。当然,确定一些指标来衡量测试的有效性在很多场合还是很有必要的,至少对于那些不想了解测试任务的细节而又要做出测试相关判断的管理者们是不可或缺的。但是,如果你不是更关注表面上的测试有效性,而是更关注真实的测试有效性,也是说你更关心的是真实的系统的质量,你不得不关注测试过程内容、关注测试工作细节,因为质量其实也是一种感觉-用户可能会说“我不知道什么样的质量是好的,反正我用了以后知道好不好了”。