探索式测试--第三章(局部探索式测试法)--读书笔记

本书为James Whittaker编写。本书写的是一种比其他任何缺陷都重要的特殊缺陷:即逃过所有各种检测手段而最终存在于发布产品中的缺陷。本书是作者设计“漫游”这个隐喻来指导软件测试。写本书对作者本人来说是一种享受,对读者来说也是一种享受。希望大家仔细品读。
第三章 局部探索式测试法
想不想测试软件
测试软件这种高度复杂的产品,如果不知道正确结果是什么,质量标准定义又很含糊不清,这活儿几乎没法干。在缺少必要信息的情况下,进行软件测试的困难度比它应有的要大得多。
欣赏软件测试的高度复杂性和艰巨性。测试是一个不停进行 抉择的过程。本章讲述的就是局部选择。它包括测试人员在使用探索式测试方法探索软件功能所要做出的各种细节决定。
局部探索式测试法有一个好处就是测试人员不需哟啊知道很多信息就可以完成任务。局部性测试的重点是把测试经验、专业知识、软件在操作环境下如何构建和运行的知识结合在一起,使我们在测试中做出正确决定。
根据软件的各种属性,我将决策分为5部分: 输入、状态、代码路径、用户数据和执行环境。这些都是探索式测试人员在测试时必须关注的。
测试就是有所变,有所不变
我们必须在测试时确定所有可能发生变化的因素,在要求我们 选择某些变量和 去掉其它变量时,我们必须做出明智的 决定
这把测试工作 简化为先在所有输入的全体集合中选择一个子集,然后在输入时使用 选中的子集,最后通过 推理认定是否这些输入已经足够多了。我们唯一的希望就寄托在正确决定我们需要变动的输入上。本文讲述的知识可以帮助我们更好、更巧妙地进行测试,从而最大限度地发现软件设计和实现中的重要缺陷。
用户输入
第一个要面对的无穷可能就是用户输入。
用户输入的基本知识
什么是输入?
输入指的是由环境产生的一种刺激,该刺激导致被测试的应用程序有所响应。
总之,输入必须导致软件执行某些代码,并以某种方式作出反应。
输入大致分为以下两类: 原子输入和 抽象输入。
因为输入可以接收的可能值实在太多,所以必须把它 抽象化。任何一个特定应用程序可以接受的原子输入的数量都是 无穷的。测试人员必须下苦功夫学习如何在各种不同的输入中选择出 最佳的一个。
实际情况比这还要复杂。如果我们只从需要研究如何从一堆原子输入中找出一个最佳 子集,软件测试就比现在我们实际面对的简单得多。还有两个因素让输入选择问题比我们想象得更复杂。首先是各种输入之间会相互 影响,从而造成软件失效。然后,输入这些值时的先后 顺序也会导致问题。
如何测试用户输入
首先我们必须意识到我们正在测试的软件和其他软件并没有什么不同。它们都会执行四个基本任务,即 接受输入产生输出存储数据进行运算。本书中可以获得一些通用的知识,再把它们应用到各自测试的软件上去,也就是按照测试应用程序的特定输入方式来输入数据,以及按照这些应用程序规定的方式和运行环境交互。
合法输入和非法输入
首先让我们理解 正向测试和 逆向测试的概念。这两者都需要,对于某些应用领域内的程序,逆向测试尤其重要,所以我们必须找到一个用于分析合法输入和分析不合法输入的策略。
测试人员应该 牢记,大多数开发人员不喜欢编写错误处理代码。
开发人员有三种基本方式来定义错误处理程序,它们分别是输入筛选器、输入检查和使用异常。
输入筛选器
输入筛选器用于防止非法的输入值被传递给应用软件的功能代码。
从测试的角度,对于输入筛选器,我们需要检查如下几个方面:
第一,开发人员是否正确地实现了该功能?如果开发人员从一开始就把合法输入与非法输入区分错误,可以预见导致的结果就是该部分会有比较严重的缺陷。
第二,是否可以绕过屏蔽器?
输入检查
输入检查输入应用程序代码主线的一部分,通常通过类似IF、THEN、ELSE结构的语句来实现。它们会接受一个输入值, 如果输入值合法, 那么接着运行处理它, 否则就产生一条错误消息并中止处理。
探索式测试法的测试人员必须牢牢抓住显示的错误信息,我的建议是必须仔细阅读每一条错误信息,检查该信息是否写错了,错误信息还可以透露出开发人员编程时的一些想法。
输入检查和异常处理的根本差别在于代码的位置,当程序从外部接收到输入值后,一般紧接着就是输入检查的代码。读入输入值的代码之后会紧跟着一个语句,用于检查输入值是否合法,所以显示出的错误信息会非常精确。如果错误信息比较笼统,往往表示这里使用的是异常处理的方式。
使用异常
本质上而言,异常处理代码可以处理各种各样的软件失效情况,不单单局限于非法输入。
这也表明,由异常处理代码产生的错误信息相对于由特定的输入检查产生的错误信息来说,一般都更笼统、含糊。
如果测试人员看见这样一个空泛的通用出错信息,我的建议是接着反复测试同一函数,继续使用刚才引发异常的输入数据,或者是稍微修改一下,看看会不会导致出错。尝试运行其他一些要调用该函数的测试用例,看看会发生什么情况。接连不断地引发异常很可能会让程序彻底失常。
非法输入应该被忽略,或者应该触发出错信息。应该按照规格说明书所定义的来正常处理合法的输入,产生合理的效果。如果你观察到的和前述情形有任何不同,表明你已找到了一个有效的软件缺陷。
常规输入还是非常规输入?
一个常规输入表示没有特定的格式或含义,可以直接使用于被测试软件。非常规输入只在那些比较特殊的情况下才会发生,或者完全是由于某个机缘巧合才会发生。
所有和Ctrl、Alt、Esc按键组合的字符都算得上是特殊字符,还有一些特殊字符与软件运行的平台相关。每一个操作系统、编程语言、浏览器和运行时环境都有一些规定的保留词,它们具有特殊的含义。
默认输入或用户提供的输入?
通常这些默认的情况要么被 忽视,要么没经过深思熟虑。
除了测试 输入 任何值,还有很多 其他东西可以测试。在看见开发人员设置的默认值后,首要任务是把该默认值 删除,留下一个 空白的字段。接着就是试试在默认值 附近的一些其它值。
一个字段如果被预先设置好默认值,便和不含默认值的字段在程序处理时往往有很大的 不同,测试人员如果愿意在这上面花费一些额外的时间,肯定会获得回报。
使用输出来指导输入选择
一些属性(如类型、长度、大小、值等)很适宜作为测试输入对象。选择输出的另一种方法是考察它可能会导致哪些输出结果。
先明确自己希望软件会产生什么样的反应,然后确定哪些输入会引发相应输出,然后在测试中使用这些输入值。
测试人员积极主动地从输出结果来思考整个问题。有一种方式相对而言比较被动一些,但有时它也非常有效,那就是 先观察输出结果,然后 再选择新的 输入,并保证新的输出是重新计算后的结果,或者是确保新的输出结果和原先不同。
还有一种从被动观察输出结果衍生出来的测试方法是寻找那些被保存起来的输出结果。如果这些值是可以改变的,一定要试试去改动这些值或者改动他们的功能,这样可以测试该值是否在原有的值上被重新生成了。测试人员对每一个功能都需要运行这样的测试。
输入选择的复杂性只是测试人员在软件测试中最先遭遇的技术难题。不断地对软件进行输入后,就出现了软件状态的问题。
状态
软件状态的基本知识
可以这么来看待软件状态,在我们选择下一步使用哪个输入时,必须考虑从前使用过的那些输入所造成的累积效应。
软件的一个状态就是状态空间中的一个点,它由所有内部数据结构的取值来唯一确定。
状态空间是由软件内部所有变量构成的一个交叉积。
如何测试软件状态
应用程序和其运行环境进行交互和接收到的所有输入导致软件状态发生变化。软件接收到输入,并在内部存储这些输入值之后,软件状态就会发生变化。测试人员就是要测试这些状态变化的情况。
软件状态可以看成是用于描述软件记住过去发生的所有输入和输出的一种方式。状态可以是临时的,也可以是长期保存的,这两种情况一般被称为数据辖域,检查软件是否正确地实现了数据辖域也是一个很重要的测试。
很多临时或被长期保持的数据并不能被直接观测到,必须通过它们对软件行为的影响来推测他们的值。测试人员要根据自己拥有的时间和预算,并结合考虑最终用户可以承担怎么样的风险,来确定在这些限制条件下如何来测试尽量多的组合。
输入和状态之间的关系相当关键,但无论是从局部或全局来看,它都是测试中的一个难点。
  • 使用状态信息来帮助寻找相关的输入
测试输入的各种组合可以说是测试的一个基本常识。如果两个或更多个输入在某种程度上是相关联的,那么它们应该放在一起测试。
  • 使用状态信息来辨识重要的输入序列
当一个输入导致状态信息被更新时,紧接着再多次使用同样的输入会导致一连串的变化。如果状态变化在某种方式上被累加起来,就必须考虑是否会发生溢出。通过观察被测应用程序中状态的累积程度,然后重复使用相同或不同的输入来检验这种累积是否会带来某些副作用。
代码路径
一连串的代码语句在软件中构成了一个代码路径。一个程序有很多条代码路径,总量非常大。
测试人员必须明确知道程序里可能有哪些分支,并理解哪些输入会导致软件走这条分支而不是另一条。这不是一个简单的任务,特别是要求测试人员不接触源代码或者不使用那些可以把输入映射到代码覆盖率工具时。如果某些代码路径没有被测试到,它们中就很有可能存在软件缺陷。
通常,循环条件的取值和用户输入息息相关。
下文会详细探讨多个可以用来提高代码路径覆盖率的特定策略。
用户数据
测试环境中设置这样一个数据存储。实际上,要做到这一点出乎意料的困难。
首先,随着真实用户数据库中数据被不断地添加和修改,常年累月积累下来的数据会变得非常多。
其次,真实用户的数据通常包含测试人员不了解的很多相互关系和结构,而且测试人员往往也无法推测真实数据中可能会有什么样的关系和结构。
还有,数据量大时,在哪里可以放得下这些数据也是问题。
简单的解决方案,用真实数据库来进行测试。
最后,处理真实用户数据时必须解决的“用户隐私”问题。
综上所述,不管有没有用户的真实数据,测试人员的麻烦都不少!
运行环境
当软件被安装到一个崭新的却它从来没见过的环境中时,还可能会失效。这是因为环境本身就算是一种输入源,所以测试人员在产品发布之前必须尽量尝试各种各样地用户环境。
任何可以影响被测试软件行为的因素都是运行环境的一部分,在测试中都必须考虑到。
从影响应用程序的角度来说,用户数据属于是一种比 较被动的方式(数据都在那儿,就等着运行测试用例时去使用它们)。运行环境则不同,它会 积极主动地和被测程序进行有针对性的交互。它为软件提供 输入,同时接收软件的 输出。运行环境非常关键,同时又很难测试。
小结
输入、代码路径、状态、被存储的数据和运行环境等,这里有太多太多的因素,而每种因素又有太多的变化可能,这一切使得软件测试变得极其复杂。无论是想通过在测试之前预先编制好测试计划,或者试图使用探索式的方法在测试和计划之间不停地转换,来解决这个无穷变化的问题,都可以说是难如登天。最终无论做了哪些测试,软件测试的复杂性都决定了我们所作的总是远远不够的。软件测试也一样,探索式测试试图把制定计划、进行测试、重新制定计划等多个过程有机地结合起来,每次只前进一小步,但这每一步都是由软件过去和当前的运行状况、软件在测试时表现出来的各种行为和软件运行时留下的种种蛛丝马迹来即时确定的。
测试本身很复杂,但是有效地利用探索式测试技术可以帮助我们驯服这匹桀骜不驯的烈马,从而发布一个高质量的软件产品。





猜你喜欢

转载自blog.csdn.net/zimingzim/article/details/81037450
今日推荐