错误发现的越早,改正错误的成本越低,正确改正错误的可能性也越大。
1. 代码检查与走查
代码检查、走查以及可用性测试是三种主要的人工测试方法。这些方法可以应用在软件开发的任何阶段。
含义:代码检查与走查都要求人们组成一个小组来阅读或直观检查特定的程序,一组开发人员对代码进行审核,其中和只有一个人是代码的作者。
优点:代码走查优点在于比原作者更为有效,而且一旦发现错误,就能在代码中对其进行精确定位,这就降低了调试的成本。
以上这些方法通常会有效地查找出30%~70%的错误,这些方法不能有效的查找出高层次的设计错误,例如在软件需求分析阶段的错误。而且程序中的错误总数始终是未知的。
2. 代码检查
代码检查是以组为单位阅读代码,它是一系列规程和错误检查技术的集合。
2.1. 代码检查小组
一个代码检查小组通常由四个人组成,其中一人发挥着协调作用、一个人是代码的作者,还包括一名测试专家。协调人应该是一个称职的程序员,但不是该程序的编码人员(可以理解为领导),不需要对程序的细节理解的很清楚。
协调人的职责如下:
-
为代码检查分发材料、安排进程。
-
在代码检查中起主导作用。
-
记录发现的所有错误。
-
确保所有错误随后得到改正。
2.2. 检查议程与注意事项
检查时,需要注意以下两点:
-
有程序编码人员逐条语句讲诉程序的逻辑结构。
-
参考常见的编码错误列表分析程序。
2.3. 对事不对人
检查过程中,必须树立正确的态度,如果程序员将代码检查视为对其人格的攻击、采取防范的态度,那么检查就不会有效果。
2.4. 代码检查的衍生功效
-
程序员通常会得到编程风格、算法选择以及编程技术等方面的反馈信息。
-
其他参与者也可以通过接触程序员的错误和编程风格而同样受益匪浅。
-
增强项目中团队的凝聚力,减少消极人际关系滋长。
-
代码检查是能否在早期发现程序中脆弱部位的方式之一。
3. 用于代码检查的错误列表
代码检查过程的一个重要部分就是对照一份错误列表,来检查程序是否存在常见错误。
3.1 数据引用错误
-
是否有引用的变量未赋值或未初始化。
-
对于所有的数组引用,是否每一个下标的值都在相应规定的界限之内?
-
对于所有的数组引用,是否每一个下标的值都是整数?虽然在某些语言中不是错误的,但这样做很危险。
-
对于所有的通过指针或引用变量的引用,当前引用的内存单元是否分配?
-
如果一个内存区域具有不同属性的别名,当通过别名进行引用时,内存区域中的数据值是否具有正确的属性?
-
变量值的类型或属性是否与编译器所预期的一致?
-
在使用的计算机上,当内存分配的单元小于内存可寻址的单元大小时,是否存在直接或间接的寻址错误?
-
当使用指针或引用变量时,被引用的内存的属性是否与编译器所预期的一致?
-
假如一个数据结构在多个过程或子程序中被引用,那么每个过程或子程序对该结构的定义是否都相同?
-
如果字符串有索引,当数组进行索引操作或下标引用,字符串的边界取值是否有“仅差一个”的错误?
-
对于面向对象的语言,是否所有的继承需求都在实现类中得到了满足?
3.2. 数据声明错误
-
是否所有的变量都进行了明确的声明?
-
如果变量所有的属性在声明中没有明确说明,那么默认的属性能否被正确理解?
-
如果变量在声明语句中被初始化,那么它的初始化是否正确?
-
是否每个变量都被赋予了正确的长度和数据类型?
-
变量的初始化是否与其存储空间的类型一致?
-
是否存在着相似名称的变量?
3.3. 运算错误
-
是否存在不一致的数据类型(如非算术类型)的变量间的运算?
-
是否有混合模式的运算?
-
是否有相同数据类型、不同字长变量间的运算?
-
赋值语句的目标变量的数据类型是否小于右边表达式的数据类型或结果?
-
在表达式的运算中是否存在表达式向上或向下溢出的情况?
-
除法运算中的除数是否可能为0?
-
如果计算机表达变量的基本方式基于二进制的,那么运算结果是否不精确?
-
在特定场合,变量的值是否超出了有意义的范围?
-
对于包含一个以上操作符的表达式,复制顺序和操作符的优先顺序是否正确?
-
整数的运算是否有使用不当的情况,尤其是除法?
3.4. 比较错误
-
是否存在不同类型变量间的比较?
-
是否粗在混合模式的比较运算?
-
比较运算符是否正确?
-
布尔表达式是否正确?
-
比较运算是否与布尔表达式相混合?
-
是否存在二进制小数的比较?
-
操作符的优先顺序是否被正确理解?
-
编译器对布尔表达式的计算方式是否被正确理解?
3.5. 控制流程错误
-
是否超出了多条分支路径?
-
是否每个循环都终止了?
-
是否每个程序都终止了?
-
是否存在由于入口条件不满足而跳过的循环体?
-
可能的循环越界是否正确?
-
是否存在“仅差一个”的迭代错误?
-
DO/END语句是否匹配?
-
是否存在不能穷尽的判断?
-
输出信息中是否有文字或语法错误?
3.6 接口错误
-
形参的数量是否等于实参的数量?
-
形参的属性是否与实参的属性相匹配?
-
形参的量纲是否与实参的量纲相匹配?
-
传递给被调用模块的实参个数是否等于其形参个数?
-
传递给被调用模块的实参属性是否与其形参属性匹配?
-
传递给被调用模块的实参量纲是否与其形参量纲匹配?
-
调用内部函数的实参的数量、属性、顺序是否正确?
-
是否引用与当前入口点无关的形参?
-
是否改变了某个原本仅为输入值的形参?
-
全局变量的定义在模块间是否一致?
-
常熟是否以实参形式传递过?
3.7 输入/输出错误
-
文件属性是否正确?
-
OPEN语句是否正确?
-
I/O语句是否符合格式规范?
-
缓冲大小与记录大小是否匹配?
-
文件在使用前是否打开?
-
文件在使用后是否关闭?
-
文件结束条件是否被正确处理?
-
是否处理了I/O错误?
3.8 其他检查
-
在交叉引用列表中是否存在未引用过的变量?
-
属性列表是否与预期的相一致?
-
是否存在“警告”或“提示”信息?
-
是否对输入的合法性进行了检查?
-
是否遗漏了某个功能?
4. 代码走查
代码检查与代码走查很相似,都是以小组为单位进行代码阅读,是一系列规程和错误检查的集合。
代码走查一般由三至五个人组成:
-
一人扮演类似代码检查过程中的“协调人”角色。
-
一个人担任秘书的角色(记录所有查出的错误)。
-
一人担任测试人员。
-
该程序的开发人员。
其他的人员可以由以下组成:
-
一位极富经验的程序员。
-
一位程序设计语言专家。
-
一位程序员新手。
-
最终维护程序的人员。
-
一位来自其他不同项目的人员。
-
一位来自该软件编程小组的程序员。
5. 桌面检查
人工查找错误的第三种过程是古老的桌面的检查方法。
桌面检查可以视为由担任进行的代码检查或代码走查:有一个人阅读程序,对照错误列表检查程序,对程序推演测试数据。