《软件测试的艺术》第三章 代码检查、走查和评审

《软件测试的艺术》第三章 代码检查、走查和评审

    • 3.1 代码检查与走查
    • 3.2 代码检查
      • 3.2.1 代码检查小组
      • 3.2.2 检查议程与注意事项
      • 3.2.3 对事不对人,和人有关的注意事项
      • 3.2.4 代码检查的衍生功效
    • 3.3 用于代码检查的错误列表
      • 3.3.1 数据引用错误
      • 3.3.2 数据声明错误
      • 3.3.3 运算错误
      • 3.3.4 比较错误
      • 3.3.5 控制流程错误
      • 3.3.6 接口错误
      • 3.3.7 输入/输出错误
      • 3.3.8 其他检查
    • 3.4 代码走查
      • 3.4.1 人员组成
      • 3.4.2 具体过程
    • 3.5 桌面检查
    • 3.6 同行评审
    • 3.7 小结

3.1 代码检查与走查

相同点:

  1. 代码检查和走查都需要人们组成一个小组来阅读或直观检查特定的程序。无论采用哪种方法,参加者都需要完成一些准备工作。准备工作的高潮是在参加者会议上进行的所谓“头脑风暴会”。“头脑风暴会”的目标是找出错误来,但不必找出改正错误的方法。换句话说,是测试,而不是调试。
  2. 在典型的程序中,这些方法通常会有效地查找出30%~70%的逻辑设计和编码错误。但是,这些方法不能有效地查找出高层次的设计错误,例如在软件需求分析阶段的错误。
  3. 代码检查/走查与基于计算机的测试是互补的。

3.2 代码检查

所谓代码检查,是以组为单位阅读代码,它是一系列规程和错误检查技术的集合。代码检查是能够在早期发现程序中脆弱部位的方法之一,有助于在测试过程中将更多的注意力集中在这些脆弱地方。

3.2.1 代码检查小组

一个代码检查小组通常由四人组成,其中一人发挥着协调作用。协调人应该是个称职的程序员,但不是该程序的编码人员,不需要对程序的细节了解得很清楚。

协调人的职责:

  • 为代码检查分发材料、安排进程。
  • 在代码检查中起主导作用。
  • 记录发现的所有错误。
  • 确保所有错误随后得到改正。

3.2.2 检查议程与注意事项

在代码检查之前的几天,协调人将程序清单和设计规范分发给其他成员。所有成员应在检查之前熟悉这些材料。

检查进行时,主要进行两项活动:

  1. 由程序编码人员逐条语句讲述程序的逻辑结构。在讲述过程中,小组的其他人员应提问题,判断是否存在错误。在讲述中,很可能是程序编码人员本人而不是其他小组成员发现了大部分错误。换句话说,对着大家大声朗读程序,这种简单的做法看来是一个非常有效的错误检查方法。
  2. 参考常见的编码错误列表分析程序。

协调人负责确保会议的讨论高效地进行、每个参与者都将注意力集中在查找错误而不是修正错误(错误的修正由程序员在检查会议之后完成)。

在代码检查的时间及地点的选择上,应避免所有的外部干扰。代码检查会议的理想时间应在90~120分钟。由于开会是一项繁重的脑力劳动,会议时间越长效率越低。大多数的代码检查都是按每小时大约阅读150行代码的速度进行。因此,对大型软件的检查应安排多个代码检查会议同时进行,每个代码检查会议处理一个或几个模块或子程序。

3.2.3 对事不对人,和人有关的注意事项

程序员必须怀着非自我本位的态度来对待检查过程,对整个过程采取积极和建设性的态度:代码检查的目的是发现程序中的错误,从而改进软件的质量。正因为这个原因,大多数人建议应对代码检查的结果进行保密,仅限于参与者范围内部。尤其是管理人员想利用代码检查的结果,那么就与检查过程的目的背道而驰了。

3.2.4 代码检查的衍生功效

  1. 程序员通常会得到编程风格、算法选择及编程技术等方面的反馈信息。
  2. 其他参与者也可以通过接触程序员的错误和编程风格而同样受益匪浅。

3.3 用于代码检查的错误列表

3.3.1 数据引用错误

  1. 是否有引用的变量未赋值或未初始化/li>
  2. 对于所有的数组引用,是否每一个下标的值都在相应维规定的界限之内/li>
  3. 对于所有的数组引用,是否每一个下标的值都是整数/li>
  4. 对于所有的通过指针或引用变量的引用,当前引用的内存单元是否分配/li>
  5. 如果一个内存区域具有不同属性的别名,当通过别名进行引用时,内存区域中的数据值是否具有正确的属性/li>
  6. 变量值的类型或属性是否与编译器所预期一致/li>
  7. 在使用的计算机上,当内存分配的单元小于内存可寻址的单元大小时,是否存在直接或间接的寻址错误/li>
  8. 当使用指针或引用变量时,被引用的内存的属性是否与编译器所预期的一致/li>
  9. 假如一个数据结构在多个过程或子程序中被引用,那么每个过程或子程序对该结构的定义是否都相同/li>
  10. 如果字符串有索引,当对数组进行索引操作或下标引用,字符串的边界取值是否有“仅差一个”(off-by-one)的错误/li>
  11. 对于面向对象的语言,是否所有的继承需求都在实现类中得到了满足/li>

3.3.2 数据声明错误

  1. 是否所有变量都进行了明确的声明/li>
  2. 如果变量所有的属性在声明中没有明确说明,那么默认的属性能否被正确理解/li>
  3. 如果变量在声明语句中被初始化,那么它的初始化是否正确/li>
  4. 是否每个变量都被赋予了正确的长度和数据类型/li>
  5. 变量的初始化是否与其存储空间的类型一致/li>
  6. 是否存在着相似名称的变量/li>

3.3.3 运算错误

  1. 是否存在不一致的数据类型(如非算术类型)的变量间的运算/li>
  2. 是否有混合模式的运算/li>
  3. 是否有相同数据类型、不同字长变量间的运算/li>
  4. 赋值语句的目标变量的数据类型是否小于右边表达式的数据类型或结果/li>
  5. 在表达式的运算中是否存在表达式向上或向下溢出的情况/li>
  6. 除法运算中的除数是否可能为0/li>
  7. 如果计算机表达变量的基本方式是基于二进制的,那么运算结果是否不精确/li>
  8. 在特定场合,变量的值是否超出了有意义的范围/li>
  9. 对于包含一个以上操作符的表达式,赋值顺序和操作符的优先顺序是否正确br> 10.整数的运算是否有使用不当的情况,尤其是除法/li>

3.3.4 比较错误

  1. 是否有不同数据类型的变量之间的比较运算/li>
  2. 是否有混合模式的比较运算,或不同长度的变量间的比较运算果有,应确保程序能正确理解转换规则。
  3. 比较运算符是否正确/li>
  4. 每个布尔表达式所叙述的内容是否都正确/li>
  5. 布尔运算符的操作数是否是布尔类型的较运算符和布尔运算符是否错误地混在了一起/li>
  6. 在二进制的计算机上,是否有用二进制表示的小数或浮点数的比较运算/li>
  7. 对于那些包含一个以上布尔运算符的表达式,赋值顺序以及运算符的优先顺序是否正确/li>
  8. 编译器计算布尔表达式的方式是否会对程序产生影响/li>

3.3.5 控制流程错误

  1. 如果程序包含多条分支路径,索引变量的值是否会大于可能的分支数量/li>
  2. 是否所有的循环最终都终止了/li>
  3. 程序、模块或子程序是否最终都终止了/li>
  4. 由于实际情况没有满足循环的入口条件,循环体是否有可能从未执行过果确实发生这种情况,这里是否是一处疏漏/li>
  5. 如果循环同时由迭代变量和一个布尔条件所控制(如一个搜索循环),如果循环越界了,后果会如何/li>
  6. 是否存在off-by-one的错误,如迭代数量恰恰多一次或少一次在从0开始的循环中是常见的错误。
  7. 如果编程语言中有语句组或代码块的概念,是否每一组语句都有一个明确的while语句,并且do语句也与其相应的语句组相对应者,是否每一个左括 都对应有一个右括 /li>
  8. 是否存在不能穷尽的判断/li>

3.3.6 接口错误

  1. 被调用模块接收到的形参数量是否等于调用模块发送的实参数量序是否正确/li>
  2. 实参的属性是否与相应形参的属性相匹配/li>
  3. 实参的量纲是否与对应形参的量纲相匹配/li>
  4. 此模块传递给彼模块的实参的数量,是否等于彼模块期望的形参数量/li>
  5. 此模块传递给彼模块的实参的属性,是否与彼模块相应形参的属性相匹配/li>
  6. 此模块传递给彼模块的实参的量纲,是否与彼模块相应形参的量纲相匹配/li>
  7. 如果调用了内置函数,实参的数量、属性、顺序是否都正确/li>
  8. 如果某个模块或类有多个入口点,是否引用了与当前入口点无关的形参/li>
  9. 是否有子程序改变了某个原本仅为输入值的形参/li>
  10. 如果存在全局变量,在所有引用它们的模块中,它们的定义和属性是否相同/li>
  11. 常数是否以实参形式传递过/li>

3.3.7 输入/输出错误

  1. 如果对文件明确声明过,其属性是否正确/li>
  2. 打开文件的语句中各属性的设置是否正确/li>
  3. 格式规范是否与I/O语句中的信息相吻合/li>
  4. 是否有足够的可用内存空间,来保留程序将读取的文件/li>
  5. 是否所有的文件在使用之前都打开了/li>
  6. 是否所有的文件在使用之后都关闭了/li>
  7. 是否判断文件结束的条件,并正确处理/li>
  8. 对I/O出错情况处理是否正确/li>
  9. 任何打印或显示的文本信息中是否存在拼写或语法错误/li>
  10. 程序是否正确处理了类似于“File Not Found”这样的错误/li>

3.3.8 其他检查

  1. 如果编译器建立了一个标识符交叉引用列表,那么对该列表进行检查,查看是否有变量从未引用过,或仅被引用过一次。
  2. 如果编译器建立了一个属性列表,那么对每个变量的属性进行检查,确保没有赋予过不希望的默认属性值。
  3. 如果程序编译通过了,但计算机提供了一个或多个“警告”或“提示”信息,应对此逐一进行认真检查。
  4. 程序或模块是否具有足够的鲁棒性就是说,它是否对其输入的合法性进行了检查/li>
  5. 程序是否遗漏了某个功能/li>

3.4 代码走查

3.4.1 人员组成

就像代码检查一样,代码走查也是采用持续一至两个小时的不间断会议的形式。代码走查小组由三至五人组成,其中一个人扮演类似代码检查过程中“协调人”的角色,一个人担任秘书(负责记录所有查出的错误)的角色,还有一个人担任测试人员。关于这三到五个人的组成结构,有各种各样的建议。当然,程序员应该是其中之一。我们建议另外的参与者应该包括:

  • 一位极富经验的程序员;
  • 一位程序设计语言专家;
  • 一位程序员新手(可以给出新颖、不带偏见的观点);
  • 最终维护程序的人员
  • 一位来自其他不同项目的人员;
  • 一位来自该软件编程小组的程序员。

3.4.2 具体过程

开始的过程与代码检查相同:参与者在走查会议的前几天得到材料,这样可以专心钻研程序。然而走查会议的规程则不相同:代码走查的参与者“使用了计算机”。被指定为测试人员的那个人会带着一些书面的测试用例来参加会议。在会议期间,每个测试用例都在人们脑子进行推演。也就是说,把测试数据沿程序的逻辑结构走一遍。程序的状态记录在纸张或者白板上以供见识。在大多数代码走查中,很多问题是在向程序员提问的过程中发现的,而不是由测试用例本身直接发现的。

3.5 桌面检查

桌面检查可视为由单人进行的代码检查或代码走查:由一个人阅读程序,对照错误列表检查程序,对程序推演测试数据。

3.6 同行评审

同行评审是一种依据程序整体质量、可维护性、可扩展性、易用性和清晰性对匿名程序进行评价的技术。该项技术的目的是为程序员提供自我评价的手段。
同行评审

3.7 小结

本章讨论了软件开发人员通常不会考虑到的一种测试形式——人工测试。大多数人认为,因为程序是为了供机器执行而编写的,那么也应由机器来对程序进行测试。这种想法是有问题的。人工测试方法在暴露错误方面是很有成效的。实际上,大多数软件项目都应该使用到以下的人工测试方法:

  • 利用错误列表进行代码检查
  • 小组代码走查
  • 桌面检查
  • 同行评审

另一种人工测试(基于人的测试)就是可用性测试,这是一种黑盒技术测试,需要测试人员站在最终用户实用的角度来评估软件的可用性程度。

声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!

上一篇 2021年5月5日
下一篇 2021年5月5日

相关推荐