生活中有这么一种现象:如果你关注某些东西,它会经常出现在你眼前,例如一个不出名的歌手的名字,一种动物的卡通形象,某个非常专业的术语,等等等等。这种现象也叫做“孕妇效应”。还有类似的一种效应叫做“视网膜效应”,它讲的是:你有什么东西或者特质你特别容易在别处发现你有的这类东西和特质。干了多年测试的我会经常发现日常使用的系统中有很多的bug,而我老婆发现不了。要说的事儿是“重现难以重现的bug”,这件事儿在本周共遇见了4次:第一次是微博上有一篇《程序员,你调试过的难的 Bug 是?》(后面会附上);第二次是一个同事跟我抱怨,好几个bug难以重现特心烦,并问我怎么处理比较好;第三次是本周上线的产品出现了一个当时难以重现的bug,我们对它做了初步的分析;第四次是翻看史亮写的书《软件测试实战》,偶尔翻了翻,竟然看到一小节在写“处理难以处理的缺陷”。这时候,脑子里很多东西汇集到了一起,我想还是记录一下吧。下面是正文:
  也许测试人员(尤其是对新手来说)在工作过程中不愿遇到的一件事情是:在测试过程中发现了一个问题,觉得是bug,再试的时候又正常了。碰到这样的事情,职业素养和测试人员长期养成的死磕的习性会让她们觉得不能放过这个bug,但是重现这样的bug有时候需要花费大量的时间,有的时候还有一些盲目性(因为黑盒测试的缘故,很多内部状态是不可见的,因此无法获取有效的信息来做跟踪),效率较为低下。在实际工作中,时间和进度摆在那里,在经历了多次痛苦的失败尝试之后,测试人员的处理方法一般会有如下几种:1.向开发人员寻求帮助来重现bug;2.当做一个issue报给开发人员。可是这样的做法存在如下问题:
  1.开发人员责任心不够强,不愿意花太多精力去求证这件事情,常见的回复是:在我这儿没事儿啊,我也重现不了,bug关了吧。结果随后在生产系统上,bug又开始sui随机出现了。
  2.跟测试人员不擅长编码和调试一样,开发人员并不擅长找出bug。经过一番尝试以后,他们也找不出什么问题来,常见的回复同第一条是一样的。bug上线后又出现的宿命也是一样的。
  这时候,真正的问题来了:如何捕捉难以重现的bug?这件事儿对于测试人员来说这么难么?
  答案并不那么乐观,重现“难以”重现的bug本来是一件“难以”完成的事情。但“难以”并不是不可能,通过一系列的测试、分析方法,我们是能够抽丝剥茧把绝大部分隐藏的很深的bug揪出来的,当然有的时候你要考虑投入产出比,但投入产出比不是本篇要考虑的,本篇只讲一些我积累的经验。
  为什么不能重现bug?
  大的原因是:测试人员对被测物的了解还不够深入。
  我曾经做过一段很长时间的收集和统计,那些被称作过“难以重现”的bug后都可以分为如下几类:
  1.环境的变更造成了bug难以重现,这里的环境包括了:基础软硬件环境(操作系统、网络、存储、中间件、容器等等),被测物自身发生了某些变更。环境的变更一般是由于多人共用环境造成的,也有少量情况下是系统内部或者时间触发的变更(这类bug非常难重现)。
  2.没有找到真正引发bug的操作。这些操作往往是一些不怎么显而易见的操作,测试人员在不经意间完成,而又忽略了这一操作,以致难于重现bug。
  3.没有找到真正会引发bug的操作序列。很多bug的重现需要满足多个条件。在满足多个条件的状态下,你做了对应的操作,bug才会被触发。
  4.bug必须使用特殊的数据才会出现,测试人员没有意识到她使用的数据的特殊性。一种比较难搞的情况是:同一组输入,在不同情况下(不是不同的业务情况)输入会被转化成不同的数据。我曾经见到过这么个例子,程序员用系统当前时间作为随机数的种子来生成id,但是id设置的比较短,一个存储的操作使用这个id,在一些情况下,发生了冲突,当时做功能测试这种小概率事件耗费了测试人员大量时间也没有稳定重现,还是在性能测试的阶段测试了出来。
  5.测试人员由于错误操作,出现了误报(这很常见)。比如,记得自己执行了step3,其实没有,或者没有正确执行step却觉得正确执行了。
  怎样对付这样的bug呢?
  我喜欢James Bach 说的那句话:测试像CSI。CSI是Criminal Scene Investigation 的缩写,也是我非常喜欢的美国系列剧。

  从我来看CSI的精髓在于:仔细观察,详细记录,科学分析,严密推理,有序求证,大胆假设,持续不懈,团队协作和一点儿运气。找bug其实和CSI探员做犯罪现场调查没什么太大区别。得知道,你工作的重要性一点儿不亚于CSI探员。