这次想和大家聊聊探索式测试的问题,这次是用涂鸦的方式。

  什么是探索式测试
  探索式测试(Explorer Testing)早是由测试专家CemKaner博士在1983年提出的,早讨论探索式测试的书,应该是《软件测试的经验与教训》(由CemKanner,JamesBach和BretPettichord合著),不过这书现在已经买不到了。
  借敏捷的东风,探索式测试这个概念在中国测试行业还是小火了一把的:传统的测试流程,需求分析、用例设计什么的,很费工夫不说,还完全架不住需求频繁的变化,在敏捷下,这一套严谨的做法反而成了项目的“负担”。于是大家把视线转移到了探索式测试上,希望探索式测试能够减少测试在文档上的投入,可以更多的聚焦产品,进行更快速的测试。
  在这样的思路下,很多测试者跃跃欲试,开展了轰轰烈烈的探索式测试活动。公司的、团体组织的各种线上线下的活动也如雨后春笋般出现了。但我发现很多同学在参加了探索式测试后反而迷茫了,多的问题是,探索式和我以前的测试到底有什么不同?
  有人说探索式测试更强调测试方法,掌握探索式测试后测试者可以用各种手段来折磨软件系统以发现系统的bug,但很多测试者会说我用所谓的传统测试,也很会找bug啊。有人说探索式测试更强调主观能动性,能够更主动的去做发散测试,探索系统的bug。但测试者又会说,我在传统测试中也是这样做的啊。
  我们究竟该如何去理解探索式测试呢?
  首先,探索式测试是一种软件测试风格(style)。
  而不是一种具体的软件测试技术(比如性能测试,等价类分析等)。
  也不是在某个测试阶段才能做的测试。
  更不是敏捷下特有的软件测试方法。
  探索式测试作为一种思维方法(approach),强调要根据当前的实际情况(context-driventesting,很多材料翻译的都是“上下文语境驱动”,非常不好理解,我觉得用中国的老话来解释是要根据当前的实际情况,具体问题具体分析)来选择合适的测试技术,进行测试。至于你用的是什么方法,什么技术,在何时展开,用的是敏捷还是瀑布都没有关系。
  这可以解释大家的疑惑原因了——探索式测试并不是什么新的东西,我相信无论你现在用的是怎样的测试模式,探索式测试多多少少都会在你的测试思维中。只是我们可能没有意识到,没有系统的去思考总结过,更没有通过刻意的去练习去提升自己在这方面的能力。所以在我们看到探索式测试的时候,才会觉得既熟悉,又陌生。
  我们的话题,是想和大家一起来梳理一下探索式测试,把大家有些忽视的探索式测试的这部分测试思维拿出来,来做一次系统的总结和思考。
  探索式测试本质是测试策略
  作为测试者,你也许没有意识到,探索式测试,本质是一种策略。
  和世界万物一样,被测对象也是时刻处于变化和发展中的——每一行代码的改变,都会让被测对象变得和之前不同。每个版本都是一个不同的产品,这需要我们根据每个版本的特点来选择不同的测试方法来测试它。
  找到这些不同本身是个探索的过程——被测系统的复杂度决定了我们不可能一下子看到系统所欲的变化,这需要我们一边探索,一边根据系统的反馈来总结,调整下一步的探索点。这是探索式测试重要的思维模型CPIE模型,如下图所示:

  收集(Collation):收集所有关于测试对象的信息并去理解这些信息。
  划分优先级(Prioritization):对所有需要测试的任务进行优先级的划分。
  分析调研(Investigation):对测试的任务进行仔细分析,预测可能输出的结果。
  实验(Experimentation):进行测试实验,确认测试结果和预期是否符合。分析是否需要修改测试策略和方法。如有需要,进入“收集”阶段。
  事实上,如果我们在测试中可以做到“测试—总结—再测试”,是在践行探索式测试了。不过现在我们是把探索式测试作为方法论来讨论,和我们无意识做的探索式测试相比,CPIE强调了“优先级”。
  讲到这里,我们先讲一下“发散测试”这个概念。很多同学都不会区分探索式测试和发散测试,很多同学甚至将两者直接划等号。事实上,发散测试和探索式测试都需要对探索被测系统,但发散测试是想到哪里立马去测试,天马行空很随意;而探索式测试需要在测试之前分析一下,看看这个探索是否值得(优先级)。除此之外,发散测试在测试之前不太关心预期结果,是测了再说;探索式测试会在测试之前分析结果——显然结果分析更有利于我们确定这项测试的优先级。
  为什么我们说探索式测试的本质是一种测试策略,这是因为探索式测试需要我们有“取舍”的能力。不是说我们把测试思维做得够发散,能够想到别人想不到的测试点够了,厉害了,还要会分析,懂得如何在有限的时间中去舍弃掉一些测试项,然后可以更深入全面的对测试重点进行测试。
  进行探索式测试
  在探索式测试中我们该如何“取舍”呢?这要从“进行探索式测试”来开始讲了。
  确定测试范围
  和所有测试一样,我们先要确实测试的范围。
  探索式测试的范围可以分为如下三类,如下图所示:
  “全局场景探索”:准备进行探索的对象是整个系统。
  “特性漫游探索”:准备进行探索的对象是整个特性。
  “局部功能点探索测试”:准备进行探索的对象是某个具体的功能。

  根据被测对象的特点来选择测试方法
  接下来我们可以分析我们即将要测试的对象的特点,然后根据它的特点来选择合适的测试方法。如下图所示。

  如果“特性”同时具备了多个区域的特征,那将这个特性分别划到这些区域中去。如果我们是对一个产品中的特性来划分区域,划分完成后,可能会像图中所看到的那样,存在相互重叠的情况,这没关系,你可以用多种方法来进行测试。
  接下来我们来看看这些不同区的测试方法:
  1.历史区测试方法
  “历史区测试法”针对的“老代码”,即在前几个版本已经存在的软件特性,也包括那些用于修复已知缺陷的代码。
  “历史区测试法”是一种有效的测试方法,因为对于软件的“缺陷”来说,历史常常会重演——我们经常在测试中发现,之前修复的缺陷在后面测试的时候又发现了,或是在后面的测试中又发现了类似的缺陷,因此多花一些时间重新测试那些曾含有很多缺陷的代码是特别重要的。
  下表总结了“历史区测试法”中包含的“探索式测试方法”,供读者参考:
  恶邻测试法:是指那些缺陷横行的代码段,测试人员应该在这些区域尽量多花时间。
  博物馆测试法:重视老的可执行文件和那些遗留代码,另外还包括累积许久没有执行过的用例,确保他们和新增代码享受同等待遇。
  上一版本测试法检查那些在新版本中无法再运行的测试用例,以确保产品没有遗漏必需的功能,也是说如果当前产品构造是对先前版本的更新,必须先运行先前版本上的支持的所有场景和测试用例。