第6章 检查代码
一、静态白盒测试:检查设计和代码
静态白盒测试是在不执行软件的条件下有条理地仔细审查软件设计、体系结构和代码,从而找出软件缺陷的过程,有时称为结构化分析。进行静态白盒测试的首要原因是尽早发现软件缺陷,以找出动态黑盒测试难以发现或隔离的软件缺陷。进行静态白盒测试的另外一个好处是,为黑盒测试员在接受软件进行测试时设计和应用测试用例提供思路。
二、正式审查
正式审查就是进行静态白盒测试的过程。
正式审查有4个基本要素:
1、 确定问题。审查的目的是找出软件的问题——不仅是出错的项目,还包括遗漏项目。
2、 遵守规则。审查要遵守一套固定的规则,规则可能设定要审查的代码量,花费多少时间,哪些内容要做评价等。
3、 准备。每一个参与者都为审查做准备,并尽自己的力量。在审查过程中找出的问题大部分是在准备期间发现的,而不是实际审查期间。
4、 编写报告。审查小组必须做出审查结果的书面总结报告,并使报告便于开发小组的成员使用。
进行正式审查要按照已经建立起来的过程执行。如果审查正确地进行,就可以证明这是早期发现软件缺陷的好方法。
除了发现问题,坚持正式审查还有一些间接效果:
1、 交流。正式报告中未包含的信息得以交流。
2、 质量。程序员的代码经过逐个功能、逐行代码仔细复查,常常会使程序员变得更加仔细。
3、 小组同志化。如果审查正确进行,就会建立软件测试员和程序员对双方技艺的相互尊重,并且更好地了解相互的工作及需求。
4、 解决方案。尽管是否讨论解决方案取决于审查的规则,但是解决方案应该用于处理严重问题。在审查的范围之外讨论解决方案也许更有效。
正式审查的三种类型:
1、 同事审查
召集小组成员进行初次正式审查最简单的方法是通过同事审查的方式。同事审查常常仅在编写代码或设计体系结构的程序员,以及充当审查者的其他一两个程序员和测试员之间进行。
2、 走查
走查是比同事审查更正规化的下一步。走查中编写代码的程序员像5人小组或其他的程序员和测试员组成的小组做正式表述。审查人员应该在审查之前接到软件拷贝,以便检查并编写备注和问题,在审查过程中提问。审查人员之中至少有一位资深程序员是很重要的。
3、 检验
检验是最正式的审查类型,具有高度组织化,要求每一个参与者都接受训练。检验与同事审查和走查的不同之处在于表述代码的人不是原来的程序员。这就迫使他学习和了解要表述的材料,从而有可能在检验会议上提出不同的看法和解释。
其余的参与者称为检验员,其职责是从不同的角度,例如用户、测试员或者产品支持人员的角度审查代码。这有助于从不同视角来审查产品,通常可以指出不同的软件缺陷。检查员甚至要担负着倒过来审查代码的责任确保材料的彻底和完整。
三、编码标准和规范
坚持标准和规范的三个重要的原因:
1、 可靠性。事实证明按照某种标准或规范编写的代码比不这样做的代码更加可靠和安全。
2、 可读性/维护性。符合设备标准和规范的代码易于阅读、理解和维护。
3、 移植性。代码经常需要在不同的硬件中运行,或者使用不同的编译器编译。如果代码符合设备标准,迁移到另一个平台就会轻而易举,甚至完全没有障碍。
标准由4个主要部分组成:
1、 标题。描述标准包含的主题。
2、 标准(或者规范)。描述标准或规范内容,解释哪些允许哪些不允许。
3、 解释说明。给出标准背后的原因,以使程序员理解这为什么这样作是好的编程习惯。
4、 示例。给出如何使用标准的简单程序示例。这不是必需的。
四、通用代码审查清单
1、数据引用错误
数据引用错误是指使用未经正确声明和初始化的变量、常量、数组、字符串或记录而导致的软件缺陷。
2、 数据声明错误
数据声明缺陷产生的原因是不正确地声明或使用变量和常量。
3、 计算错误
计算或者运算错误实质上是糟糕的数学问题。计算无法得到预期结果。
4、 比较错误
小于、大于、等于、不等于、真、假。比较和判断错误很可能是由于边界条件问题。
5、 控制流程错误
控制流程错误的原因是编程语言中循环等控制结构未按预期方式工作。它们通常由计算或者比较错误直接或间接造成。
6、 子程序参数错误
子程序参数错误的来源是软件子程序不正确地传递数据。
7、 输入/输出错误
输入/输出错误包括文件读取、接受键盘或者鼠标输入以及向打印机或者屏幕等输出设备写入错误。
8、 其他检查
这个压轴清单定义了一些不适合放在其他类别的条目。如:软件是否使用其他外语;软件是否要移植到其他编译器和CPU,是否具有这样做的许可;是否考虑了兼容性;程序编译是否产生“警告”或者“提示”信息等。
五、小结
检查代码(静态白盒测试)被证实是早期发现软件缺陷最有效的方法。虽然这是一项需要大量准备工作才能有成效的任务,但是许多研究表明花费的时间与得到的好处相比是值得的。

?
第7章 带上X光眼镜测试软件
一、动态白盒测试
动态白盒测试是指利用查看代码功能和实现方式得到的信息来确定哪些需要测试、哪些不要测试、如何开展测试。动态白盒测试的另一个常用名称是结构化测试,因为软件测试员可以查看并使用代码的内部结构,从而设计和执行测试。
动态白盒测试不仅仅是查看代码的运行情况,还包括直接测试和控制软件。动态白盒测试包括以下4个部分:
1、 直接测试底层函数、过程、子程序和库。
2、 以完整程序的方式从顶层测试软件,但是根据对软件运行的了解调整测试用例。
3、 从软件获得读取变量和状态信息的访问权,以便确定测试与预期结果是否相符,同时,强制软件以正常测试难以实现的方式运行。
4、 估算执行测试时“命中”的代码量和具体代码,然后调整测试,去掉多余的测试用例,补充遗漏的用例。
二、动态白盒测试和调试
这两项技术表面上很相似,因为它们都包括处理软件缺陷和查看代码的过程,但是它们的目标大不相同。动态白盒测试的目标是寻找软件缺陷,调试的目标是修复缺陷。
软件测试员应该把问题缩减为能够演示软件缺陷的最简化测试用例。如果是白盒测试,甚至还要包括那些值得怀疑的代码行信息。进行调试的程序员从这里继续,判断到底是什么导致软件缺陷,并设法修复。
三、分段测试
从测试的角度看,产生高额费用有如下两个原因:
a. 难以,有时甚至不可能找出导致问题的原因。
b. 某些软件缺陷掩盖了其他软件缺陷。
1、 单元测试和集成测试
在底层进行的测试称为单元测试或者模块测试。单元经过测试,底层软件缺陷被找出并修复之后,就集成在一起,对模块的组合进行集成测试。这个不断增加的测试过程继续进行,加入越来越多的软件片段,直至整个产品(至少是产品的主要部分)在称为系统测试的过程中一起测试。
这种递增测试有两条途径:自底向上和自顶向下。
(1) 自底向上
自底向上测试中,要编写测试驱动模块,测试驱动模块以和将来真正模块同样的方式挂接,向处于测试的模块发送测试用例数据,接受返回结果,验证结果是否正确。采取这种方式,可以对整个软件进行非常全面的测试,为它提供全部类型和数量的数据,甚至高层难以发送的数据。
(2) 自顶向下
自顶向下测试有点像小规模的大爆炸测试,先测试高层的软件,然后测试它们下一层的。
2、 单元测试示例
书中以测试一个把ASCII字符转换为整数值的常用函数为例,说明单元测试的步骤:
(1) 分析该模块属于程序中的底层模块,可以由高层模块调用,但是自己不能调用其他模块。合理的做法是编写一个测试驱动以独立于程序其他部分的形式测验该模块。
(2) 分析说明书,确定应该采用的黑盒测试用例,然后运用等价类划分技术减少测试用例集合。
(3) 研究代码看函数是如何实现的,利用模块的白盒知识增减测试用例。
注意:在进行白盒子测试之前,一定要根据说明书建立黑盒测试用例。用这种方式可以真正测试模块的功能和作用。如果先从模块的白盒角度建立测试用例,检查代码,就会偏向于以模块工作方式建立测试用例。程序员或许误解了说明,于是测试用例就会不对。虽然测试用例精确完整地测试了模块,但是可能不准确,因为没有测试预期的操作。
四、数据覆盖
像黑盒测试那样把软件代码分成数据和状态(或者程序流程)。从同样的角度看软件,可以相当容易地把得到的白盒信息映射到已经写完的黑盒测试用例上。
1、 数据流
数据流覆盖主要是指在软件中完全跟踪一批数据。
通过黑盒测试,只能知道变量开始和结束的值。通过动态白盒测试,还可以在程序运行期间检查变量的中间值。根据观察结果就可以决定更改某些测试用例,保证变量取得感兴趣的、甚至具有风险的中间值。
2、 次边界
如果进行白盒测试,就需要仔细检查代码,找到次边界条件,并建立能测试它们的测试用例。询问编写代码的程序员是否知道这些条件,并对内部数据表给予特别的注意,因为这里聚集了大量次边界条件。
3、 公式和等式
公式和等式通常深藏于代码中,从外部看,其形式和影响不是非常明显。撇开代码中的公式和等式,查看它们使用的变量,在程序正常输入和输出之外,为其建立测试用例和等价划分。
4、 错误强制
错误强制是在调试器中测试的程序,可以强制改变变量的值,借此执行其他方式难以实现的测试用例。
在使用错误强制时,小心不要设置现实世界中不可能出现的情况。如果仔细选择了错误强制情况,并和程序员一起反复检查以确认它们是合法的,错误强制就是一个有效的工具。
五、代码覆盖
与黑盒测试一样,测试数据只是一半工作。为了全面地覆盖,还必须测试程序的状态以及程序流程,必须设法进入和退出每一个模块,执行每一行代码,进入软件每一条逻辑和决策分支。这种类型的测试叫做代码覆盖测试。
书中介绍代码覆盖的两种形式:
(1) 最简单的形式是利用编译环境的调试器通过单步执行程序查看代码。其适用于小程序或单独模块。
(2) 对于大多数程序进行代码覆盖测试要用到称为代码覆盖率分析器的专用工具。其挂接在正在测试的软件中,当执行测试用例时在后台执行。每当执行一个函数、一行代码或一个逻辑决策分支时,分析器就记录相应的信息。从中可以获得指示软件哪些部分被执行,哪些部分未被执行的统计结果。
1、 程序语句和代码行覆盖
代码覆盖最直接的形式称为语句覆盖或代码行覆盖。如果在测试软件的同时监视语句覆盖,目标就是保证程序中每一条语句最少执行一次。
注意:即使全部语句都被执行了,但是不能说走遍了软件的所有路径。
2、 分支覆盖
   试图覆盖软件中的所有路径称为路径覆盖。路径测试最简单的形式称为分支覆盖测试。
书中以举例的方式,讲述了分支覆盖,但没有给出其具体定义,以下是我在网上找到的定义:
分支覆盖又称为判定覆盖,它要求设计足够多的测试用例,使得程序中每个判定至少有一次为真值,有一次为假值,即:程序中的每个分支至少执行一次。每个判断的取真、取假至少执行一次。
3、 条件覆盖
以下是网上找到的定义:
条件覆盖要求设计足够多的测试用例,使得判定中的每个条件获得各种可能的结果,即每个条件至少有一次为真值,有一次为假值。
书中例子举的还是很好的,比较容易理解。
在动态分析技术中,最重要的技术是路径和分支测试。下面介绍的是书中没有说到的覆盖测试方法:
(1)判定/条件覆盖:设计足够多的测试用例,使得判定中每个条件的所有可能结果至少出现一次,每个判定本身所有可能结果也至少出现一次。
(2)条件组合覆盖:要求设计足够多的测试用例,使得每个判定中条件结果的所有可能组合至少出现一次。
(3)路径覆盖:设计足够的测试用例,覆盖程序中所有可能的路径。
六、小结
以上第4-7章是本书的第二部分,讲述了软件测试的基础:
1、 静态黑盒测试是指检查产品说明书,并在软件编写之前找出问题。
2、 动态黑盒测试是指在不了解软件如何工作的前提下进行测试。
3、 静态白盒测试是指通过正式审查和检验检查代码的细节。
4、 动态白盒测试是指在看到软件的工作方式时,根据获得的信息对软件进行测试。

本文出自 “我的E博客” 博客,请务必保留此出处http://yunzhongyi.blog.51cto.com/4363700/801859