探索性测试总结笔记

探索性测试

在开始实践敏捷的时候,就一直谈论着探索性测试。尝试了许多方式,多角度覆盖、路径漫游、逆向思维等等,虽然取得了一定的效果,但仍无法很自信的回答团队做的确实是探索性测试。因为一直忙测试开发的工作,而忽略了对测试工作本身的总结和思考。所以最近特意看了一些资料和书,才把探索性测试的方法论整个整理出来。(本文许多论点取自James A. Whittaker的探索式软件测试一书)

 

什么是探索性测试

在测试行业非常喜欢炒作的是自动化测试,但是自动化测试有一个致命的弱点就是“预言家难题”,意思是如何才能知道被测试的软件确实完成了它应该完成的任务,预言如何才能精准无任何差错?机器毕竟不是人,它只能按照固定的步骤来执行计算、判断,例如自动化运行中途出现:操作系统升级重启、机器断网、浏览器故障重启了、页面刷新较慢元素在该有的时间内没出现、HTTP丢包等等任何一些不稳定,自动化的流程就很容易崩溃并最终等待人的介入。所以过度依赖自动化是不明智的,手工测试永远都会继续发挥着作用。

 

如果想发现应用程序业务逻辑相关的缺陷,充分发挥主观能动性的手工测试也是最理想的选择。但随着软件测试的发展,手工测试越来越倾向于精心策划。现代软件项目是庞大的人员成本是有限的,如何保证在有限的时间内做最正确的事,需要手工测试在开展之前,有明确的战略和方向,但又必须预留一定的发挥空间让每个人的大脑可以充分运转起来,在测试的过程中随机应变。我们把这种测试方式称作探索性测试:它鼓励测试人员一边测试、一边计划、他们使用在测试中收集到的信息,影响自己进行测试的实际方式。

 

理解探索性测试有两个前提:第一,测试之前一定会有一个全局的方针战略,即整体的测试计划,它可以避免走错大方向,该测的部分没有覆盖到,计划之外的部分却投入了大量时间。第二,测试一旦开始,没有固定的思路,测试人员不受任何先入为主的条条框框约束,根据测试途中获取的信息,指导各自走不同的路径,最终目的就是发现潜藏的缺陷。

 

探索性测试的种类

JW的书中用了一个最恰当的比如来描述探索性测试的方法论,即把测试比做一场旅程。测试的对象就是旅游的目的地(比如说像伦敦这样一座古老的城市),软件的缺陷就比作是在这座城市里所有有趣的角落。显然,在软件发布周期规定的有限时间里,你不可能把城市的每一个角落都逛遍,这样你也就不可能发现城市里每一个有趣吸引你的角落,你得严格制定你的行程和各种后备方案,但同时你也会在旅途中遇到许多突发状况,临时改变你的路线,就为了能走遍最好玩的地方,往往有些角落是沿途发现的没出现在你的计划中。这样来比喻有计划又鼓励自由发挥的探索性测试,真是太贴切了!

 

为了继续发挥这个比喻的效果,我还是引用JW书中的一些描述吧。我们在旅程开始之前,首先会做一些全局的计划,比如把一座城市划分为商业区、旅游景点、娱乐区、旅馆住宿区、历史区还有治安不太好的旧城区,这就像软件产品里的各个模块一样,有主打卖点的核心功能、也有辅助功能和历史遗留代码等(例如商业区就代表了真正产生经济效益的实际业务完成区域)。当我们设计路线的时候,通常我们会拿着一份城市的地图来做规划,同样的道理我们也可以拿着一份产品的说明书(F1效应)来设计探索性测试的路线。

 

这里列举了一些书中总结出来的探索性测试方法:

  • 指南测试法:城市的题图通常都会标注一些热门的旅游景点,测试这些热门的区域是非常重要的。不管在任何一次发布的过程中,核心功能是肯定要覆盖到的。指南测试要求测试人员严格按照用户手册的建议执行操作,有可能是手册描述不到位或者核心功能并不像宣传的那样好。
  • 卖点测试法:此方法是鼓励测试人员观看销售给客户演示的Demo,理解销售的角度哪些功能对客户来说是最大的卖点,他们未必就是核心功能,但值得测试人员把它们当核心功能来对待。同时,也许刁钻的客户会提出各种质疑,这些质疑和稀奇古怪的问题也可以纳入测试人员的设计中。
  • 地标测试法: 在旅游的时候,如果我们设计了要到访的地方,通常会在地图上插上旗子,这就是地标。但是没有人规定我们应该按照何种顺序去到访这些地标。不同的测试人员可能会选择不同的顺序,有经验的测试人员会基于对软件产品架构和技术层面的理解,采取一些古怪的路径但更可能发现缺陷。
  • 极限测试法:向软件提出难以回答的问题,比如最大可以发挥到什么程度,承受多少用户,承载多少数据。那个特性或功能会把软件逼到极限运作,哪些输入和数据会消耗软件最多的计算能力?哪些输入可能绕过它的错误检测?
  • 快递测试法:快递运送的货物,就好比软件里的数据,结果不同的地点转接,拆包装包最终到底目的地。所以快递测试专注的是数据,跟随它们走遍整个软件。
  • 深夜测试法:城市灯火阑珊会在午夜过后逐渐安静下来,商场店铺纷纷打烊。但是软件不应该停止工作,软件测试人员有时应该刻意的关注在冷门时间段软件所做的附属工作,比如数据备份归档、维护监控任务的运行等等。
  • 博物馆测试法:这是针对软件的遗留代码,保留了些许年代的一些功能,找出它们来验证是否有出现失效。当初开发它们的时候,甚至可能缺乏文档,但这并不意味着它们应该被忽略。
  • 深巷测试法:在每个城市,都有些地方并不吸引游客意味着不吸引人群,但作为测试人员来说,反而是这种最不可能被用到或者最不吸引用户的特性,容易潜藏着难以发现的Bug。
  • 通宵测试法:繁华的都市总会有通宵热闹的地方,比如夜总会KTV之类的,它们从不中断。那么应用程序是否也能坚持到最后呢?当它面临持续不断的调用、输入、重读重写之类的操作,如果运行时间足够长,就很可能会出问题,内存会需要回收、数据需要清空,永远不要关闭它,保持不间断的运行。(更多的时候会采用自动化或者机器人思想)
  • 长路径测试法:把那个在应用程序埋藏最深的界面当做测试目标(离起始点最远的那个界面),观察经过的每一个界面
  • 超模测试法:针对UI的表面测试,衡量软件的展现能力,像T型台的超模那样,不去关注她们幕后的辛酸痛苦劳累,跳出产品专家或测试的头衔,以普通观众的角度,去关注那些能看到的界面展现,元素是否被正确绘制、是否难看、颜色风格是否一致、界面的切换变化是否表意清晰?
  • 取消测试法:此方法的思想是启动了立即停止,特别是一些运行流程比较耗时的功能如备份还原或者搜索,在启动之后,立即取消。发散一点还可以变成,启动一个耗时操作,不停止立即启动另外一个耗时操作,以此来检测应用程序的自我清除能力。
  • 懒汉测试法:选择尽可能少的输入,能不输入尽量不输入,能不修改尽量不修改,观察应用程序是否能响应得出正确结果。
  • 反叛测试法:你见过去酒吧不喝酒点果汁的么?反叛思想要求输入最不可能的数据,或者已知的而已输入,测试人员可以采用逆向思维、明知一些数据违反规则,却偏偏要采用这样的数据,或者不按照正确的顺序来输入。
  • 强迫症测试法:测试人员强迫软件一边又一边接受同样的数据,反复执行同样的操作,最重要的特点就是重复。此种思维方式,常常打破了开发人员设计代码的思路,他们预想着你会按步骤操作,却不曾考虑过你反复的执行第一步应该如何处理。

 

更多的讨论

探索性测试蕴含着丰富的策略,将结构化思想与自由的探索方式很好的结合起来,在发现缺陷以及检验正确性上有显著的效果。它能覆盖单一场景无法覆盖的情况,更好的模拟真实用户的行为。那么如何开始呢?用户故事(User Story)会是个绝佳的起点,通常实施敏捷的团队会要求创建用户故事,在用户故事中描述需求和产品的行为。测试人员可以向用户故事衍生出的场景中注入合适的变化,通过有系统的考虑输入选择、数据使用和环境条件,一个场景可以衍生出多个测试用例。

 

详细一点,给场景注入变化的手段包括:

  • 插入步骤:增加更多次的数据输入、或增加附加的输入、又或者访问相关的原来不包含的页面,前提是当附加页面与目标页面有共享的操作或者数据,这样的关联性加入才有意义。
  • 删除步骤:逐步去掉冗余和可选的步骤,每次只删除一个步骤,直到获得一个最短的测试用例
  • 替换步骤:如果某些操作可以有多种方法可以完成,就可以用替换其中的某些步骤来尝试不同的路径
  • 重复步骤:理解要重复的步骤和重复的顺序才会使得重复的加入有意义
  • 替换数据:前提是理解应用软件的数据源,如果数据源停止工作或者无法连接时软件会变成什么样?
  • 替换环境:包括硬件、不同版本的浏览器、或者修改本地设置(禁用Cookie之类的)

无论使用何种测试技术,从刚开始就要有效的计划和调剂测试资源,以保证团队成功的机会。使用探索性测试也为测试人员提供了更多的机会积极参与和承担责任,因为他们可能在途中另避蹊径找到一些创新的思路和手段来检测缺陷。

 

即使是探索性测试,也无法避免在测试工作中面临的五大难题:漫无目的、重复性、暂时性、单调性、健忘性;只是探索性测试能够基本将这些困难很好的解决。这里其实个人感触最深的是重复性的问题,每一次有代码提交也好,功能增加也好,不可避免的要做许多重复的工作,没有任何人能自信满满的说,那些功能因为在上个月我们测试过了,所以这次就能够直接忽略。

 

这里也推荐一个经典的比喻,软件的Bug就像是农场里的害虫一样,软件测试一遍又一遍的覆盖检测扫面就像农民一次次的喷洒农药一样,只要你的面积足够大,总是能发现并杀死大部分的害虫,但是也总会有一小部分的害虫是逐渐适应了你的农药对它免疫了的。这时候,无论你重复多少次,这些害虫也是无法被杀死的,最终就导致了没有任何软件能无缺陷的发布。其实按照农民针对害虫农药免疫的问题,不难想到解决的办法就是:改变配方。当你使用探索性测试改变思路,去做下一次的回归测试的时候,因为你的操作顺序变了,测试数据变了,那些对以往测试免疫Bug也会因为无法适应而逐渐显露出来并被干掉。但是注意你注入的变化带来的配方改变,并不是武断随意的,而是充分基于测试人员对产品技术、功能、架构的理解,融入过往经验真正有价值的变化。(最终这些变化都体现在了用例的设计中)

 

探索性测试也并不意味着完全的手工,因为要最大程度的发挥人的主观能动性,就势必要避免人的时间花在繁琐重复的劳动中,所以适当的开发工具降低人无谓的劳动是很有必要的。同时,测试开始之后比较侧重当前的状况,精力大多被当前发生的事情所吸引,而没有功夫去思考下一步,或者说靠脑袋来记忆一定是不可靠的,例如这个界面被测试过了多少次,被多少人测试过,每个API又被覆盖了多少次…… 测试用例的频繁更新并不是解决这类记忆问题的好方法,我们依然可以想办法从工具开发的角度,帮我们记录追踪这类信息。例如:一条漫游路径可以代表实际任何数量的测试用例,如果我们努力的把漫游路径映射到软件特性和缺陷上,留下来的记录会帮助所有测试人员了解内部情况,包括哪些测试方法是有效的,哪些地方是最频繁出问题的。

 

展望未来的软件测试应该是什么样子?在Google如何做测试中谈到过这个话题,不过在JW的书中,又有一些新鲜的概念,比如测试百科。它强调测试是一个经验不断积累的过程,包括测试用例的设计、工具的使用和性能指标的参照等等,当人们把这些为了某个产品而付出研究的成果总结成更加通用的可参考或借鉴使用的一条一条经验,就形成了测试百科。它可以避免测试人员的损失给团队带来的巨大影响。而且就像写的程序代码能最大程度被复用一样,软件测试的步骤、手段、方法、策略也应该被最大程度的复用。甚至编程的时候,可以使用成熟的框架,为何测试就不能产生成熟的框架直接使用呢?


一些摘录

  • 每一个好的缺陷背后,都可能藏着一个更好的缺陷,在你确实了解缺陷的影响程度和破坏力之前永远不要停止探索。
  • 测试人员的绩效不是通过他们找到了多少Bug来评估的,而是他们究竟提高了多少开发人员的工作效率和工作质量,从而反应在产品的质量上。
  • 自动化测试在回归测试盒应用程序接口测试方面最有优势,而手工测试在验收测试盒用户界面测试上效果更佳。手工测试因为由人来做,可以执行非常复杂的业务逻辑,它虽然速度更慢但并不拖沓。自动化测试,擅长低级别的细节如不正确的返回值、错误代码、内存使用情况等,快速但阻力也巨大。
  • 测试人员当然需要读写代码,而且最好的选择是直接从产品的错误处理代码入手,这样能一眼发现何种输入数据、输入顺序能把产品逼到极限。

声明:转载请注明原文出处。


你可能感兴趣的:(Testing,Agile)