探索式测试与即兴测试(ad-hoc testing)有何区别?
探索式测试与即兴测试的都强调”即兴发挥“,利用直觉和经验,快速地试验被测试应用,并不停地调整测试策略。开发大师Andy Hunt在《Pragmatic Thinking and Learning》中指出,直觉是非显性知识的代名词,是大脑富(Rich)模式的杰出能力。如果我们只使用大脑的线性模式(语言可表达的显性知识、逻辑思维),而漠视富模式的能量,我们将浪费自身的巨大潜力。
然而人是不完美的,某些直觉可能是认知偏见或错误。这就引出了探索式测试与即兴测试的关键不同:探索式测试是带着”反思“的学习和优化过程。在探索式测试中,测试人员不断地提出假设,用测试去检验假设,通过解读测试结果来证实或推翻假设。在这个过程中,测试人员不断完善头脑中被测试应用的模型,然后利用模型、技能、经验去驱动进一步的测试。相比即兴测试不注重测试计划和设计,探索式测试在不停地优化测试模型和测试设计。因为测试设计和测试执行的切换速度很快,许多人误以为探索式测试没有测试计划和设计。实际上,这些活动是被切分到细微的时间片中,并被反复执行。
首先,探索式测试是一种软件测试风格(style),而不是一种具体的软件测试技术(如等价类划分、边界值分析、组合测试等)。作为一种思维方法,探索式测试强调依据当前语境(context)选择合适的测试技术,而不局限于特定的测试技术。虽然James A. Whittaker将他的书命名为《探索式软件测试》,该书所提出的方法集仍旧属于软件测试技术(基于系统化错误猜测和测试隐喻),而不代表整个探索式测试。Whittaker的工作是很有意义的,本文指出它不是探索式测试的全部,是为了强调:当你和别人讨论”探索式测试“时,你们得达成共识。你们是在讨论一种思考方法,还是在讨论这种思考方法指导下的测试技术。
然后,探索式测试强调独立测试人员(individual tester)的个人自由和责任(personal freedom and responsibility),其目的是为了持续优化其工作的价值(value)。测试人员应该为个人和团队负责,调动所有能量,发挥人的灵活性,在整体上持续优化个人和团队的产出。这段描述和精益生产(lean production)、敏捷软件开发的理念高度一致,这也是探索式测试受到敏捷团队欢迎的原因之一。
最后,探索测试建议在整个项目过程中(throughout the project),将测试相关学习(test-related learning)、测试设计(test design)、测试执行(test execution)和测试结果解读(test result interpretation)作为相互支持的活动(mutually supportive activities),并行地(parallel)执行。实际上,人脑难以并行地执行多项任务。探索式测试旨在将测试学习、测试设计、测试执行和测试分析做为一个循环快速地迭代,在较短的时间内(如1个小时)完成多次循环,以不断收集反馈、调整测试、优化价值。该思路再次与敏捷软件开发小步快跑、持续反馈的理念不谋而合。
用我自己个人的经验总结,如下图所示:
当测试人员面对一个网页、一个对话框或正在查看程序中某一个类的方法时,他往往需要一些很明确的建议知道他如何处理这些情况。由于这个决策过程比较短,影响范围比较小,所以测试人员在运行一个测试用例中会多达几十次地重复该过程,在一天的测试工作中,则可能需要几百次经历这样的决策过程。
局部探索式测试法有一个好处是测试人员不需要知道很多信息就可以完成这些任务。局部性测试的重点是把测试经验、专业知识、软件在操作环境下如何构建和运行的知识结合在一起,使我们在测试中做出正确的决定。
在所有细节问题都解决之后,有可能会发现我们还缺乏一个综合的测试集,该测试集用来确定软件是否已经满足正式发布所需达到的质量标准。
功能测试用例基础设计模型讲解:
1)在任何情况下都必须采用边界值分析法。这种方法设计出来的测试用例对发现程序的错误是非常有用的。
2)必要时采用等价类划分法补充测试用例。
3)对照程序逻辑,检查已设计的测试用例的逻辑覆盖程度。如果它没有达到要求的覆盖标准,则应当补充更多的测试用例。
4)如果程序的功能说明中含有输入条件的组合情况,则应该一开始就选用因果图法。
5)对于业务流清晰的系统,可以利用场景法贯穿整个测试案例过程,在案例中综合使用各种测试方法。
6)对于需求上的修改,若同个功能需要修改后端和客户端、前端才能满足该需求时,这时候在设计测试用例的时候,需要考虑到客户端的旧版本兼容问题。
7)整理功能测试用例的时候,必须跟开发确定相应的接口、参数,数据库对应的表和字段。因为用户的有些操作会入表,有些操作不入表,所以要确定好对数据库的相关操作,避免影响到统计数据。
8)对于某些需求功能在ui上会有展示要求,这里要注意对不同分辨率机型进行验证。
9)如果接入其他部门或者第三方的组件或模块,应详细了解非我方模块的各种流程尤其是异常处理,写测试用例的时候应充分覆盖。
输入input讲解:
关键点:输入是由应用程序外部触发的,并导致应用程序执行某些代码。
比如用户单击一个按钮属于一个输入,但是在文本框输入文本就不算输入,只有文本被实际传递给应用程序,应用程序有机会处理时,才算得上是一种输入。
原子输入:比如单击按钮,字符串或整数4就属于原子输入,它们都简单到不能再简单,都属于单个的事件。
各种输入之间相互影响
输入这些值时的先后顺序也会导致问题
抽象输入:有些原子输入是相互关联的,如果把这些相互关联的原子输入合并成一个抽象输入,在选择测试数据时会更有效率。整数4和整数2048都是一个特定的值(也就说是原子输入),但是测试人员也可以选择使用5或者256。所以,使用抽象术语来描述这些输入会更方便,因为这样可以把它们当成一个整体概念来对待。
各种输入之间相互影响:
测试人员必须能够识别哪些输入值和其他输入有关联,然后在同一个测试用例中使用它们,这样就可以保证这些情况被覆盖了。
输入这些值时的先后顺序也会导致问题:
测试人员必须可以枚举出那些比较恰当的顺序,然后测试它们,这样才有把握相信软件可以满足实际用户的需求。
有些原子输入是相互关联的,如果把这些相互关联的原子输入合并成一个抽象输入,在选择测试数据时会更有效率。整数4和整数2048都是一个特定的值(也就说是原子输入),但是测试人员也可以选择使用5或者256。所以,使用抽象术语来描述这些输入会更方便,因为这样可以把它们当成一个整体概念来对待。
输入筛选器讲解:
输入筛选器用于防止非法的输入值被传递给应用软件的功能代码。
目的:把那些坏的输入值挡在应用程序之外,这样开发人员就不用担心那些非法输入值了。如果一个输入值被传递给应用程序,
这个输入值就被认为是一个好的输入值,可以被安全使用,所以也就没有必要进行进一步的检验。挡程序的性能比较关键时,开发人员通常会使用这个技术。
输入筛选器不会产生错误信息,相反,输入屏蔽器默默地把非法的输入排除在外,只把合法的输入值传给应用程序。
输入检查器讲解:
输入检查属于应用程序代码主线的一部分,通常通过类似:if、else结构的语句来实现(或者switch、case结构)。
它们会接受一个输入值,如果输入值合法,那么揪着运行处理它,否则就产生一条错误信息并终止处理。
实现输入检查后会报警,通常就是显示一条错误信息,该信息会描述当前状况,并准确地表示当前的输入值出现了不合法的情况。
输入检查和异常处理的根本差别在于代码的位置,当程序从外部接受到输入值后,一般紧接着就是输入检查的代码。
读入输入值的代码之后会紧跟着一个if语句,用于检查输入值是否合法。所以显示出的错误信息会非常准确。
例如:“不允许输入负数”就是一条精确的错误信息,它告诉用户当前输入哪里出了问题,如果错误信息比较笼统,往往表示这里使用的是异常处理的方式。
错误信息还可以透露出开发人员编程时的一些想法。
相关阅读:探索式测试第一课:局部探索(下篇)
本文来自网易实践者社区,经作者李乐授权发布。