1、概念
静态测试是指不需要执行被测程序,而是人工检查或者借助专用的软件测试工具来评审软件文档或程序,度量程序静态复杂度,检查软件是否符合编程标准,寻找程序的不足之处,降低错误出现的概率。 统计表明,30%--70%的代码逻辑设计和编码缺陷可以通过静态代码分析来发现和修复。 静态测试包括代码检查、静态结构分析、代码质量度量等。
语法检查:最基本的程序静态分析,编译器完成。
非语法类型缺陷:人工或借助静态分析工具。
非语法类型缺陷:不匹配的参数、 不适当的循环嵌套和分支嵌套、 危险的递归、 未使用过的变量、 空指针的引用、 可疑的计算等。
非高质量编程隐患: 缺乏良好的编程规范 缺乏统一的编程规则等
2、代码检查
主要内容包括 :检查代码和设计的一致性,代码对标准的遵循,可读性,代码逻辑表达正确性,代码结构合理性等; 发现程序中不安全、不明确和模糊部分,找出程序中不可移植部分; 发现违背程序编写风格问题,其中包括变量检查、命名和类型审查、程序逻辑审查、程序语法检查和程序结构检查等内容。
优越性: 在实际软件开发过程中被普遍采用,测试业界实践表明,通过代码检查,可检测到程序中 30%甚至高达70%的程序逻辑设计及编码中的缺陷或者错误; 一旦发现错误,能在代码中精确定位,降低修复成本; 有时可以发现成批错误,如分散在多处的同一类型错误等。
局限性:不能有效查出高层次的设计错误、不明显的错误等
代码检查的主要方式包括 :桌面检查 代码审查 代码走查
2.1 桌面检查
程序员对自己的代码进行一次自我检查,包括阅读程序、对代码进行分析、对照错误列表检查程序、对程序推演测试数据等。
局限性:a.效率是较低。 随意性较大,检查哪些内容,如何检查,检查到何种程度?b. 自己一般不太容易发现自己程序中的问题。
2.2代码审查
由若干程序员和测试员组成小组,通过阅读、讨论、评价和审议,对程序进行静态分析的过程。让人充当计算机,把数据代入程序,模拟代码的执行,看程序能不能正常执行下去,执行过程和状态是否正确,并能最终得出符合预期的结果。
代码审查分两步:a. 负责人提前把设计规格说明书、控制流程图、程序文本及有关要求、规范等分发给小组成员,作为审查的依据。小组成员在充分阅读这些材料后,进入审查环节。 b.召开程序审查会。通过会议和集体讨论、评价和审议,以集体的智慧和不同的角度,找出程序中的问题,提出修改意见和建议。
在实践中,可以采用交叉桌面检查的方法,两个程序员可以相互交换各自的程序来做检查,而不是自己检查自己的程序。
2.3代码走查
让人充当计算机,把数据代入程序,模拟代码的执行,看程序能不能正常执行下去,执行过程和状态是否正确,并能最终得出符合预期的结果。 代码走查与代码审查都是以小组为单位进行,但代码走查重在模拟程序的执行,它需要推演每个测试用例的执行过程和结果,把测试数据沿程序的运行逻辑走一遍,过程和中间状态记录在纸张或白板上以供监视检查。
代码走查过程也分为两步:第一步把材料先发给走查小组每个成员,让他们认真研究程序,然后组织代码走查会议。 开会的过程与代码审查不同,不是简单地读程序和对照错误检查表进行检查,而是让与会者“充当计算机”,由测试人员为被测程序准备一批有代表性的测试用例,提交给走查小组,走查小组开会,一起把测试用例代入程序,模拟代码的执行,分析检查程序的执行过程和结果。
2.4 总结
代码走查与代码审查都是以小组为单位进行,但代码走查重在模拟程序的执行,它需要推演每个测试用例的执行过程和结果,把测试数据沿程序的运行逻辑走一遍,过程和中间状态记录在纸张或白板上以供监视检查。
3.常见代码审查清单
3.1数据引用错误
是否有引用的变量未赋值或未初始化? 数组引用,是否每个下标都在规定界限内? 是否有空指针引用? 假如一个数据结构在多个函数中引用,每个函数对该结构的定义是否相同? ... ...
3.2 数据声明错误
是否所有变量都进行了明确声明? 数组和字符串的初始化值是否正确? 变量是否赋予了正确的长度、类型和存储类型? 初始化是否与存储类型相一致? 是否有相似的变量名,如VOLT,VOLTS?...
3.3 运算错误
是否存在非算术运算变量间的运算? 是否有混合模式的运算,如浮点数+整数? 赋值号左边的数据类型是否小于右边的类型或计算结果? 除法运算中除数可能为0? 运算结果是否不精确?如 10*0.1 == 1.0? 整数的运算是否使用不当?如 i/2*2 == i ?
3.4 比较错误
是否有不同类型变量间的比较,如字符串与数字相比? 比较运算符是否使用正确?如 至多、至少、不小于等的理解, >= 写成 > ?? 比较运算符与布尔运算符混用? 是否有小数或者浮点数的比较运算? 运算符的优先级是否正确理解?
3.5 控制流程错误
是否所有的循环、模块或子程序最终都终止? 没有满足循环入口条件,循环体是否有可能从未执行过?遗漏? for(i<x,i<=z;i++),当初始时就有x大于z? 是否存在“仅差一个”的错误? 循环体语句块(左右花括号)是否正确使用? 是否 switch 语句有 default 情况? 循环中嵌套的 switch语句是否正确?
3.6 接口错误
实参的数量、类型、顺序等是否与形参相匹配? 实参的计量单位是否与形参一致? 如 元、万元? 如果调用了内置函数,实参的数量、属性、顺序是否正确?如 strcpy() 是否改变了某个原本仅为输入值的形参?
3.7 输入/输出错误
是否所有的文件是使用之前都打开? 是否所有的文件是使用之后都关闭? 是否有判断文件结束的条件并正确处理? 是否正确处理类似于“File Not Found”这样的错误? 打印或者显示的文本信息中是否有拼写错误?
3.8 例子
例:Java代码审查表
4.静态结构分析
例:函数调用关系图
从该函数调用关系图中,可以得到以下信息: 函数之间的调用关系符合设计规格说明书的要求; 不存在递归调用; 调用层次最深为4层; 不存在独立的和没有被调用的函数; 比较重要的函数有validate()、compareTwoStr()等。