2.2 测试的第一重境界:围着Bug转
“意识决定行动,行动决定结果”是管理学中众所周知的名言。做测试的前几年,笔者并没有这个意识,也没有主动地去思考过这个问题,但随着一个个项目任务、一桩桩事件的历练,慢慢感悟到这句话也适合对测试工作境界的理解。“心态决定命运”,“态度决定一切”,有很多名家学者都写过这方面的书籍,基本上已成了我们不可否认的真理了,但是要真正应用在自己的工作生活中,恐怕就不那么简单了。诚然,测试工作,除了需要拥有过硬的测试技术外,还必须有正确的测试心态,也正是这些心态意识左右着你的日常工作。不同的心态反映了不同的测试境界高度,最终体现出不同的结果。
围着Bug转,是测试三重境界中的第一重。概括起来,它又可以分为三个阶段,第一,发现Bug;第二,定位Bug;第三,关闭Bug。这三个阶段对测试人员的要求不仅在技术上需要逐层递进,在综合素质上也提出更高的要求。三个阶段之间环环相扣,直到Bug的生命周期结束。围着Bug转的三个阶段对测试人员的要求及Bug被发现到关闭的生命周期示意图,如图2-5所示。
图2-5 围着Bug转的三个进阶图
谈到围着Bug转的的三个阶段,不禁想起中国近代著名学者王国维在《人间词话》中提到的人生的三重境界:
“昨夜西风凋碧树,独上高楼,望尽天涯路”。
“衣带渐宽终不悔,为伊消得人憔悴”。
“众里寻他千百度,蓦然回首,那人却在灯火阑珊处”。
细细思量,感觉它们之间亦有异曲同工之处。
第一重“昨夜西风凋碧树,独上高楼,望尽天涯路”是说“古今之成大事业、大学问者,首先要树立明确的目标,即使长路漫漫,也下定决心将这条长路走下去。这是一个人在孤独之中寻找理想、寻找生命的落脚点的痛苦时刻”。围着Bug转的第一阶“发现Bug”,同样首先必须有明确清晰的目标,找Bug的过程是漫长的,反反复复、枯燥无味是工作的特点,但是为了达到目标“长路再漫漫,也得坚持走下去”,直到找到一堆堆的Bug。特别是对一些偶现的严重Bug,重现Bug的过程真如大海捞针,但是坚持就是胜利。笔者曾经在经历的一个项目中,花了近1个月的时间去重现与解决一个严重问题,最后在与开发人员的紧密合作下,终于找到问题的根源。
第二重“衣带渐宽终不悔,为伊消得人憔悴”是说“执着的追求、忘我的奋斗,直至憔悴消瘦,连衣服都变得宽大,这一切努力都是为了心中的梦想”。对应软测中围着Bug转的第二阶“定位Bug”。这一阶段不仅在技术上提出了更高的要求,还要有刻苦钻研、穷追到底、不撞南墙不回头的执著精神,直到把问题的原因搞清楚才罢休。在国内目前的测试领域,大部分公司这一步并没有要求测试人员来做,但是在国外,特别是一些知名的大公司,如在微软,几乎所有的测试人员都拥有深入调试程序的技能。它除了包含以最短路径重现问题,还要分析问题的可能结果(例如分析Bug会影响到哪些模块),甚至给开发人员提出解决方案。显然,这一步要求测试人员要比开发人员具有更高的设计分析能力、代码调试能力、解决问题的能力。读者朋友,看到这里,对一些测试专业网上常看到的“测试人员是否要懂编程”这一问题已释然于怀了吧。
第三重“众里寻他千百度,蓦然回首,那人却在灯火阑珊处”。这一阶段是指经过不断磨炼,多次的失败,某一时刻忽然灵犀一点,领悟真谛,发现自己想要的东西原来就在自己的身边或领悟后的心里。在旁人看来,他的“蓦然回首”是如何偶然而幸运,但其背后的用功之勤、平时的积累之深,又岂是常人所能坚持,所能想象的呢?这时候,世俗目标是否已经达到已不再重要,重要的是灵魂的解放和心灵的归属。对应围着Bug转的第三阶“关闭Bug”,如果仅从字面理解,很简单,不就是开发解决了Bug,回归Bug,然后把Bug关闭。如果是这样,笔者认为这种观念仍属于第一阶。第三阶的关闭Bug,是指测试人员提交一个Bug后,要有主动意识推动开发人员解决问题,并协助他们解决,只有问题解决了,软件的质量才得以提高,测试人员的最终目的才能达到。提交的有些问题严格来说,它不属于Bug,而是一种设计缺陷,此时测试人员该怎么办呢?需主动召集相关专家进行其影响面的风险分析,并跟进此问题的整个解决过程,如果风险点涉及其他专业的更改(如嵌入式软件涉及硬件、机械等方面的知识),可能需要专门成立一个专项问题解决团队,以全面解决此问题,直到各专业方向的问题解决到位,回归验证完成,此Bug方能关闭。站在Bug的生命周期角度分析,一个Bug由被发现的起点,走到被关闭的终点,才是一个合理的、完整的过程,如图2-6所示。但是要达到这一层,很可能有一大部分的工作已完全脱离了纯软件测试层面的工作,可是测试的最终目标不就是给用户一个高质量、信得过的产品吗?我们需要有这样的大气胸怀,才能把产品的测试工作做得更深远、更宽阔。
接下来结合案例对围着Bug转的三个阶段分别进行介绍。
图2-6 Bug生命周期曲线闭环图
2.2.1 独上高楼——发现Bug
【案例】
深圳九月天,仍是骄阳似火,一点没有入秋的气息。我们的办公室,中央空调照常开着,比较瘦小怕冷的小祝,还穿上了厚衣服。昨天陈老板刚把我们测试过的版本提交给合作方,今天一早,测试组的5个同事还没接到新任务,大家也就继续测试原来负责的模块。只听有同事在说“如果再发现Bug,版本已发了,怎么办呢?”“每个模块大家已交叉测试过,近1周大家基本上没提什么Bug,应该没问题了吧!”几句话闲话之后,大家又忙自己的事了。
整个上午,办公室异常安静,地上铺着地毯,即使是偶尔有同事从身旁走过,轻轻的摩擦声也是若有若无。与往日不一样的是缺少了与开发人员的争论,或许太安静了,笔者反而觉得有点不习惯。忙了一阵之后,抬头看看坐在前面的同事,还发现有人被瞌睡虫咬住了呢。在已发布版本上继续测试已测试了近两个月的模块,真像咬老菜干,越嚼越没味,说不准过几分钟,自己也被瞌睡虫找上门来了。这样的场景,这样的氛围,不知不觉熬过了2天,一个Bug都没发现,笔者心中难免有几分失意。
第三天,陈老板来上班了,但并没有给我们安排新任务,我们只好继续咬老菜干。为了不让瞌睡虫再找上门,也为了能更加集中精力测试那些看似没有Bug的软件,笔者在电脑显示屏下方显眼位置,贴上了3个大红字“找Bug”(如图2-7所示)。并在心里不断提醒自己“Bug是找不完的,并不是没有Bug了,而是你没有看到它而已”。甚至在假想着找Bug,就好像挖地雷,每走一步,都得小心谨慎,一不小心,一个Bug就从你眼皮底下悄悄地溜走了。也就是带着这种心态,这种认真谨慎,第三天终于有了突破,提交了2个Bug。一个是可能会误导用户的低级错误的错别字,另一个是属于第三方供给我们的手写识别系统的严重Bug(当时测试的是随手写掌上产品)。由于这一次的“不小心”发现了其他同事模块的低级问题,按老板的苛刻规定,那个月笔者多拿了100元的奖金,而对方却扣了100元的奖金(那时我们的每月奖金是浮动的,人均200元)。在第三方软件给我们提交了补丁包后,老板重新发了版本。不知道后来被老板提升,会不会与这次重要的事件有关。这已是过去很多年的事了,但其中的感悟,在日后的测试工作中一直伴随着笔者,那就是“不管什么时候,测试的目的必须要清楚,Bug是找不完的,并不是没有Bug了,而是你暂时没看到它”。
图2-7 沉浸在找Bug中
小贴士:
Bug是找不完的,并不是没有Bug了,而是你暂时没看到它。
或许有感于对测试正确认识带来的好处,后来在一家公司任职时,有幸与另外一些同事一起出题招聘公司的测试工程师。
以下是其中的一道选择题。
软件测试的目的是什么?
供选答案:
① 保证软件的质量,提高软件的质量。
② 验证程序的运行符合需求定义,是正确的。
③ 发现程序中的错误。
后来,我们总结了86位应聘者的答案,发现有52位的应聘者选择的是①,即近60%的应聘者认为软件测试的目的是“保证软件的质量,提高软件的质量”;选择②的有10人,约占12%;选择③的有22人,约占26%。出乎我们意料,有2人对此题做了多选,其中1人选择了①②③,另外1人选择了①③。
由于当时出题时考虑此题是放在最容易拿分的一类题(或叫送分题),但大大超出预期。笔者怀疑出的题是不是存在纰漏,于是特意又找出那本当年伴随着笔者成长、印象深刻的清华大学出版社出版、张海藩编著的《软件工程导论》,打开“第七章测试”,对测试的基本概念再次细读了一遍,其中已很清楚地提到“测试是为了发现程序中的错误而执行程序的过程”。
锁定“软件测试的目的就是发现Bug”,不管你用什么方法,黑盒还是白盒,或者是灰盒,仅是方法不同,而其聚焦点是相同的,就好像不同的人拿着不同的探测器去搜寻不同层次的Bug。有了这个清晰的目标后,所有的前期测试设计工作都需围绕如何高效发现Bug而着想,如测试方案的设计、测试用例的设计、测试执行过程的控制。尽管Bug数量不是衡量一个测试人员绩效的唯一考核点(因为Bug数量的多少与模块的复杂度、开发人员的设计水平、需求的变化等因素直接相关),但业界人士都清楚其所占的分量,可以说已成了大家心照不宣的能力判断标准之一。
2.2.2 为伊消得人憔悴——定位Bug
站在测试的角度定位Bug,可以从以下两个方面来理解。
第一,以最短路径重现必发Bug。
以最短路径重现必发Bug,也叫精益求精。很多测试朋友常问“什么样的测试工程师算是优秀的测试工程师?”笔者认为,能不能做到精益求精,正是一个优秀测试工程师的特征之一。
成就感对个人的工作心理状态影响很大,也很重要。在面试测试工程师时,面试官常会问“测试工作中,最使你有成就感的是什么?”基本上都会回答“发现了Bug”。发现了Bug,当然是好事,值得高兴,但是发现了Bug,只是意味着这个Bug被暴露出来了,它的生命周期却刚刚开始。一旦一个Bug被发现,它就成了我们的敌人,接下来开发人员要解决它,测试人员要回归它,直到最后关闭它才宣告结束。
要解决Bug,首先开发人员要能重现此Bug,在重现的基础上分析问题,进而解决问题。如果测试人员在提交的Bug步骤描述中能给出最短的必然路径,可以明显缩短开发分析问题、定位问题的时间。表面上看来只是加快了开发解决问题的速度,但由于开发解决Bug的速度加快了,发布版本自然也会更加顺利,实际上对后期的测试也争取了时间。特别是对整个项目的进度能起到积极的推动作用。但是,在测试团队中我们常会看到这样的现象,测试人员一旦发现一个Bug,便迫不及待地提到缺陷管理库上,有时描述不清楚,步骤也是含糊地写了一堆。开发人员重现来重现去都没有出来,最后只得找测试人员来重现,发现原来是漏写了某关键步骤,有时甚至测试人员本人也重现不了,免不了被开发人员鄙视一番,只好以尴尬告终。
朋友,你是提交Bug的积极分子吗?这很好。但是在提交之前,请忍耐片刻(毕竟不会因为你这个Bug晚提交几分钟,成为影响开发解决问题的瓶颈而最终影响版本的发布),对着自己填的Bug单操作一遍,然后再单击那个激动人心的“提交”按钮(因为一旦提交,意味着一个Bug的生命周期开始了),某个倒霉的开发工程师又多了一件差使。曾经在一个项目的结项总结会上,笔者亲自听一位资深的开发工程师说:“一个偶发的严重Bug,就好像一把利剑时刻悬挂在头顶上,每天都在揪着我的心,想拿下来却又谈何容易?”开发朋友的肺腑之言,其中更显测试提交必发Bug,并以最短路径重现的重要性与必要性。
第二,重现偶发Bug。
实践过的测试朋友,你是否也曾遭遇过不能重现的偶发Bug?笔者曾经看到某公司对测试人员的绩效考核中有这么一条:“提交的偶发Bug不超过本人提交Bug总数的3%。”当然,高要求是对测试人员工作的鞭策,从结果导向来说是件好事。
一次,与一位开发总监论道,他说:“在开发看来并没有偶发的Bug存在,之所以我们认为它偶发,是因为我们未找到必发的绝对路径,要么条件不符合,要么触发时机不对等。”其实,在任何一位测试人员心里,都是想把Bug重现出来,以节省更改时间。下面通过重现偶发Bug的案例,与大家分享通过强度压力测试来重现Bug的做法。
小贴士:
通过强度压力测试重现Bug,是一种耐心与技术的挑战!
下面是一个关于重现Bug的精彩案例。
【案例】
某公司研发某精密测量仪器软件,此软件有提供用户用U盘导出测量数据的功能。一天,收到一客户的投诉,说在使用仪器的此功能时发现“U盘导出功能有时会失效,重新拔插U盘后功能有效,且这种现象发生过多次”。
接到客户的投诉后,测试负责人马上组织相关测试工程师进行跟踪。经过一番沟通、了解,详细的问题描述是这样的:在仪器的USB接口上插入U盘后,进入软件的数据导出界面,按“导出”按钮,软件提示“没有发现U盘!”,但是U盘却正安安稳稳地插着,此时拔下U盘再插入,再执行导出操作可以成功导出数据。同时,也记录了客户端仪器产品的序列号,由此为索引,在公司的产品追溯库中找到了此产品的软件版本号、硬件相关配置等系列配套信息。
在获悉所需信息后,开发工程师A与测试工程师B分头行动。开发工程师A从相关代码着手分析,测试工程师B则反复地重复操作试图重现这个偶发问题。重现这种偶发Bug而做一遍遍机械式的操作,绝对是一种耐力的磨炼,这种测试方法,在测试团队中被有人戏称为“魔鬼测试法”。测试工程师B这样魔鬼式测试了一天,盼星星盼月亮似的,盼着的“没有发现U盘!”提示并没有出现。还好,开发工程师A那边排除了一些非软件原因,如U盘没有插好、U盘是否存在坏道等。
第一天没有重现此Bug,对于测试来说,工作仍需继续。测试工程师B绞尽脑汁,用尽了不同的相关发散思维,但是黑暗的道路上依然没看到一点光明。时间已是第二天下午的17:30分了(18:00下班)。可怜的B心里想着,今天重现的可能不大了,需召集相关专家会谈,想想其他办法。正这样想着的时候,B的动作放慢了,插了U盘之后,并没有着急马上按“导出”按钮,而是不经意地按了“导出”按钮,奇迹也就在这一瞬间出现了。只听,B惊呼起来:“出来了,Bug出来了!”
整个办公室的全体测试同事都站起身来,以为发生了什么事。有些同事,还马上凑过去看,好像不相信似的。B马上说“大家不许动,我要叫A来分析现场”。开发工程师A查看特意准备的调试信息,以及内部的一些其他信息记录,跟踪对应的代码块,发现相关代码在识别U盘的地方存在漏洞,但是却不能下结论说,这个问题一定是由这块代码引起的。开发工程师更改软件后,需要测试人员再进行魔鬼测试。
通过两天的魔鬼测试磨炼,测试工程师也增长了经验,写了一个自动化脚本,自动挂载U盘,模拟按键“导出”动作,然后卸载U盘,晚上让脚本自动触发,连续执行了1万次、2万次、3万次。后来,用自动脚本在原有版本同样执行上万次,也没有出来此Bug。相关人员开始怀疑自动化与人工操作的差别与问题出现有关。暂没想到其他更好的办法,只好再由B在更改后的软件上进行第三轮的魔鬼测试。
苍天不负有心人,第三天B在更改后的版本上真再现了此Bug,证实了开发人员的怀疑是正确的,也就意味着这个Bug的真正原因并没有找到。一场欢喜,一场忧,严峻的形势又使他们陷入了迷雾之中,犹如侦探小说中扣人心弦的情节,刚找到的一条线索,却发现是假象,而期望的目标又总是迟迟不能出现。
启动“专家会诊”共同切脉工作。从已明确的种种迹象出发,有专家提出应该把重点放在“分析为什么手工连续进行230~250次正常的操作时会出现识别不到U盘,而自动化脚本执行上万次都正常,它们之间的本质差别是什么?”这一句话,对开发工程师A的工作起到了指点迷津的作用,于是把分析方向转向了负责U盘识别的硬件驱动上。历经3天的分析、调试后,A终于得出结论“由于负责控制U盘驱动的芯片存在一个硬件设计缺陷,此缺陷只有在硬件寄存器复位后且复位前后的值正好相等才发生,一旦发生,则U盘识别不到”。
问题的真正原因找到了,解决Bug不费吹灰之力。更改后再提交版本给B验证,回归通过,悬在头顶上近半月的剑终于取了下来,Bug销声匿迹,永退江湖了。“U盘导出”事件,也成了某公司研发团队中的一个众所周知的“著名案例”。
为伊消得人憔悴。定位Bug的过程对测试工程师来说,是毅力与技术的双重挑战,正所谓“道路是曲折的,前途是光明的”。
2.2.3 蓦然回首——关闭Bug
“思想决定行动”,测试设计活动与测试者的心理密切相关,对软件测试的理解不同,对测试工作的要求亦会不同。
一直以来,笔者认为测试就是发现程序中的错误而执行程序的过程,并且把这句话写在工作记录本上的封面,让它每天都能提醒自己,即使换了笔记本后依然把这句话写在上面。刚开始时,这句“警示语”的确很有用,每天工作的目标很明确,就是发现Bug。曾经,Bug多的时候,一天提过30多个,有种Bug多得提不完的感觉(这种情况一般出现在新项目提交测试的前面几个版本)。正如开发同事常说的一句话“测试在笑,开发想哭”,这也从一方面说明,在工作性质上开发与测试本身就是对立的,但我们的目标是一致的,就是把产品的质量做好。
直到有一次,参加了51testing软件测试网在深圳举办的软件测试沙龙,一位代表发言提出“测试不仅仅是发现程序中的Bug,更重要的是跟踪解决这些Bug,因为只有Bug被解决了,质量才有可能提高,我们的成绩才能得以真正的体现。”多么精辟且恰到好处的总结啊!事实的确是这样,测试提交了Bug,如何说服开发人员解决这个Bug,这才是关键。我们的测试工作应当不能仅仅停留在发现Bug上,Bug只有被解决,测试人员对产品的贡献才能真正体现出来。有了这个思路,很自然地在对Bug的生命周期管理上、与开发的沟通交流上,我们会变得更加主动。
人的行为受着思维的控制,有什么样的思维就会有什么样的行动,不同的目标导致不同的结果。有了“关闭Bug”的目标,可以使测试人员在提交Bug后主动跟踪Bug的各种状态。概括来说,一个测试人员在测试执行过程中与Bug的生命周期有着以下的关系。
第一步:发现Bug。这一点是根本,它由测试人员在执行测试的过程中产生。
第二步:跟踪Bug。例如每天定时查看缺陷库上Bug的状态(开发人员处理Bug后会置它于一个合适的状态),如果几天后,此Bug的状态仍没有变化,主动与缺陷负责人交流情况,解决问题便是一种跟踪的方法。
第三步:回归Bug。开发人员解决Bug后,测试人员需及时回归,验证是否如预期解决了此Bug,有没有引出新问题?
第四步:关闭Bug。如果回归Bug通过,即验证确实此Bug不存在了,则关闭Bug,意味着它的生命周期到此结束。
除第二步外,其他都是测试人员自身要做的工作,对个人测试技术上的要求较多。测试人员提交Bug后,需要开发人员来解决Bug,也就在第二步涉及测试人员与开发人员如何有效沟通的问题。一般情况下,当测试提交Bug给某模块的开发人员后,对方会在某时间内自动处理。但是,如果测试人员不主动跟踪所提交Bug的解决情况,结果常常会出乎意料,如某些Bug会被置为“无效”或置为“不解决”。此时很多测试人员可能在心里觉得很委屈,处于第三重境界的“关闭Bug”的玄机也就在这里了。
对于测试人员来说,当然希望提交的每个Bug都能得到解决(缺陷被修正),但是为什么会遇到有一些Bug,开发人员认为“无效”或“不解决”呢?一些测试人员会找开发人员理论,但被开发人员说了一通后,就像泄了气的皮球,最后只好很不情愿地“取消关闭”此Bug。就这样一个Bug来了又去了,这当然不是我们想要的(被开发人员置为无效的Bug通常可能是非常规操作或是用户难于遇到的场景,较好的做法是置为无效或不解决的Bug提交相关专家评估它的风险)。遇到这种情况,有些测试人员会找自己的主管出面,这里充满着沟通的艺术。下面的案例便是一个关于如何与开发人员沟通、解决测试人员问题的典型例子。
【案例】
一天下午,开完部门例会的测试主管陈刚回到座位,测试工程师小楠便过来说她发现了一个关于“数据库备份的严重Bug”,开发工程师正在解决,但听开发人员说,此Bug的更改影响较大。她觉得需要搞清楚设计的原理,以及更改的影响面,这样才能做全面的回归。在与开发人员的交流中,他们显得很不耐烦,还说测试不必关心设计的细节。这让小楠很难受,她当面指出他们这样做是错误的。
看小楠委屈得眼泪都要出来的样子,陈刚表示能理解她的心情,并说往深入、全面方面分析Bug是对的,而工作交流中关于开发人员很不耐烦的事,可能是在沟通过程中存在的一些误会。
第二天,陈刚拿着一张纸(上面写着几个关于数据库设计方面的问题)、一支笔去找开发工程师,首先说明是向他请教某数据库设计方面的问题,开发人员看陈刚真诚谦虚、好学的样子,就一口气地讲了起来。讲完后,陈刚微笑着赞美他把设计的东西讲得那么清楚,同时也提出自己对如此重要的设计只理解一点点,并不全面,并说自己及测试人员都很想学习全面的设计流程细节,邀请他来给测试的全体人员进行宣讲,对产品的质量来说真是太重要了。经怎么一说,开发人员最后笑着说:“没问题,我自己开发设计过,一定能讲得出来的。”
一场不愉快的局面化解了,沟通使事情走向了美好、有效的结局。
小贴士:
卡耐基慧语:如果你想赢得人心,首先要让他相信你是最真诚的朋友。