软件测试胡侃之代码审查和代码走查

 

  • 代码检查、走查与评审

《软件测试的艺术》书中第三章讲到人工测试的代码检查、代码走查、桌面检查和同行评审。

#代码检查

Def:以组为单位阅读代码,一系列规程和错误技术的集合。

Group:代码检查小组(一般为4人)

职务

职责

备注

协调人

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

一名程序员、但不是被测程序的作者,不需要特别了解程序细节

程序编码人员

扫描二维码关注公众号,回复: 2200061 查看本文章

朗读程序并逐行讲解

即被测程序作者,也是被检查者

其他成员

提出质疑,并讨论

程序的设计人员,前提不同于编码人员

测试专家

提出质疑,并讨论

具备软件测试经验,并熟悉大部分的常见编码错误

Process:检查议程与注意事项

Step1:会议之前,协调人分发程序清单和设计规范给小组成员,所有成员在检查之前进行熟悉。

Step2:会议中,程序编码人员逐条语句讲述逻辑结构,过程中其他成员结合常见的编码错误列表分析程序,提出质疑,讨论,确认是否存在错误,协调人记录讨论过程以及错误清单。

Step3:会议结束后,协调人将错误清单提交给程序编码人员进行确认,若发现错误过多,或者某个错误涉及对程序做根本性的改动,协调人需要在错误修正后,重新安排会议再次检查。

Time:理想时间在90~120分钟,一般为每小时150行左右速度进行。因此建议每个代码检查会议处理一个或几个模块或子程序。

Error table:用于代码检查的错误列表,见附录A。

#代码走查

Def:以组为单位阅读代码,一系列规程和错误技术的集合。

Group:代码检查小组(一般为3-5人)

职务

职责

备注

协调人

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

一名程序员、但不是被测程序的作者,不需要特别了解程序细节

秘书

记录所有查出的错误

 

程序编码人员

朗读程序并逐行讲解

即被测程序作者,也是被检查者

测试人员

提出质疑,并讨论

具备软件测试经验,并熟悉大部分的常见编码错误

其他人员

提出质疑,并讨论

可以包括:

一个经验丰富的程序员;

一位程序设计语言专家;

一位程序员新手;(可以给出新颖、不带偏见的观点)

最终维护程序的人员;

一位来自其他不同项目的人员;

一位来自该软件编程小组的程序员。

Process:检查议程与注意事项

Step1:会议之前,协调人分发程序清单和设计规范给小组成员,所有成员在检查之前进行熟悉,同时测试人员提前准备一些书面测试用例(程序或模块具有代表性的输入集及预期的输出集)来参加会议

Step2:会议中,将每一个测试用例通过人脑过一遍,即输入集沿程序的逻辑结构走一遍。程序的状态(如变量的值)记录在纸张或白板上以供监视。其中测试用例尽量结构简单、数量较少。

Step3:会议结束后,秘书将错误清单提交给程序编码人员进行确认,若发现错误过多,或者某个错误涉及对程序做根本性的改动,协调人需要在错误修正后,重新安排会议再次检查。

Time:理想时间在一至两个小时。

 

#桌面检查

此方法可视为由单人进行的代码检查或代码走查:有一个人阅读程序,对照错误列表检查程序,对程序推演测试数据。缺点:缺乏约束性、违反自检原则、效率低

 

#同行评审

此方法与程序测试无关,目标不是为了发现bug,而是在自我评价和相互学习中提高代码质量。

是一种依据程序整体质量、可维护性、可扩展性、易用性和清晰性对匿名程序进行评价的技术。

Step1:选出一名程序员作为评审过程的管理员,然后由管理员选出每名6~20名参与者(具备相似背景,起码编程语言一致),组成评审团

Step2:每个参与者选出两个自己编写的程序以供评审,其中至少一个代表自身能力的好作品,集合成评审资料

Step3:随机分发给参与者,每名参与者对分到的4个程序进行评审,分为两个“最好的”,两个“较差”的程序,全过程保密。平均每名评审员每个程序时间在30分钟左右,评审完后填写一张评价表。

Step4:评审员将自己分配到的4个程序全部评审完,进行相对质量分级,分值为1~10分

参考如下标准评分(1:明确“是”、10:明确“否”):

  1. 程序是否易于理解?
  2. 高层次的设计是否可见且合理?
  3. 底层次的设计是否可见且合理?
  4. 修改此程序对评审者而言是否容易?
  5. 评审者是否会以编写出改程序而骄傲?

并给出总的评价和建议的改进意见。

Step5:会议结束,参与者会收到自己的两个程序匿名评价表,以及一个带统计的总结,说明在所有程序中程序的整体和具体得分情况,以及他对其他程序的评价与其他评审人对同一程序打分的比较分析情况。

 

  • 静态分析、代码审查与代码走查

军工软件静态测试方法一般为静态分析、代码审查和代码走查,顺序通常为静态分析、代码审查、代码走查。其中静态分析和代码审查会使用到单元测试工具。详见参见《GJB-Z 141-2004 军用软件测试指南》A.1静态测试方法

 

#静态分析

静态分析一般包括控制流分析、 数据流分析、 接口分析、 表达式分析。

  •   控制流分析

控制流分析是使用控制流程图系统地检査被测程序的控制结构的工作。控制流按照结构化程序规则和程序结构的基本要求进行程序结构检査。这些要求是被测程序不应包含:

a)  转向并不存在的语句标号;

b)  没有使用的语句标号;

c)  没有使用的子程序定义;

d)  调用并不存在的子程序;

e)  从程序入口进入后无法达到的语句;

f)  不能达到停止语句的语句。

控制流程图是一种简化的程序流程图, 控制流程图由 “节点” 和 “弧" 两种图形符号构成。

  •  数据流分析

数据流分析是用控制流程图来分析数据发生的异常情况, 这些异常包括被初始化、 被赋值或被引用过程中行为序列的异常。数据流分析也作为数据流测试的预处理过程 。

数据流分析首先建立控制流程图, 然后在控制流程图中标注某个数据对象的操作序列, 通历控制流程图, 形成这个数据对象的数据流模型, 并给出这个数据对象的初始状态, 利用数据流异常状态图分析数据对象可能的异常。

数据流分析可以査出引用未定义变量、对以前未使用的变量再次赋值等程序错误或异常情况。

  • 接口分析

接口分析主要用在程序静态分析和设计分析,接口一致性的设计分析涉及模块之间接口的一致性以及模块与外部数据库之间的一致性,程序的接口分析涉及子程序以及函数之间的接口一致性, 包括检査形参与实参的类型、数量、维数、顺序以及使用的一致性。

  • 表达式分析

表达式错误主要有以下几种:

括号使用不正确, 数组引用错误, 作为除数的变量可能为零, 作为开平方的变量可能为负, 作为正切值的变量可能为π/2 , 浮点数变量比较时产生的错误。

  • 此外, 静态分析还可以完成下述工作:

a)  提供问接涉及程序缺陷的信息:

1 )  每一类型语句出现的次数;

2)  所有变量和常量的交叉引用表;

3)  标识符的使用方式;

4)  过程的调用层次;

5)  违背编码规则;

6)  程序结构图和程序流程图;

7)  子程序规模、调用/被调用关系、扇入/扇出数。

b)  进行语法/语义分析, 提出语义或结构要点, 供进一步分析。

c)  进行符号求值。

d)  为动态测试选择测试用例进行预处理。

静态分析常需要使用软件工具进行,例如C++Test、Jtest、TestBed等单元测试工具,静态分析是在程序编译通过之后, 其它静态测试之前进行的,一般静态分析测试报告中会描述违反编码规则数、扇入扇出数大于X的个数等。

 

#代码审查

代码审查和《软件测试的艺术》中代码检查基本一致。

代码审査的测试内容: 检査代码和设计的一致性; 检査代码执行标准的情况; 检査代码逻辑表达的正确性; 检査代码结构的合理性; 检査代码的可读性。

代码审査的组织:由四人以上组成,分别为组长、资深程序员、程序编写者与专职测试人员。组长不能是被测试程序的编写者, 组长负责分配资料、安排计划、主持开会、记录并保存被发现的错误。

代码审査的过程:

a)  准备阶段:组长分发有关材料, 被测程序的设计和编码人员向审査组详细说明有关材料, 并回答审査组成员所提出的有关问题。

b)  程序阅读: 审査组人员仔细阅读代码和相关材料, 对照代码审査单, 记录问题及明显缺陷。

c)  会议审査:组长主持会议,程序员逐句阐明程序的逻辑,其他人员提出问题,利用代码审査单,进行分析讨论, 对讨论的各个问题形成结论性意见。

d)  形成报告: 会后将发现的错误形成代码审査问题表, 并交给程序开发人员。对发现错误较多或发现重大错误, 在改正错误之后再次进行会议审査。

代码审査问题表应写明所査出的错误类型、错误类别、错误严重程度、错误位置、错误原因。错误类型有文档错误、编程语言错误、逻辑错误、接口错误、数据使用错误、编程风格不当、软件多余物,错误类别有遗漏、错误、多余。这种静态测试方法是一种多人一起进行的测试活动, 要求每个人尽量多提出问題, 同时讲述程序者也会突然发现一些问题, 这时要放慢进度, 把问题分析出来 。

实际项目中代码审查也会结合单元测试工具和桌面检查等方法。

代码审查单例子:见附录B,C/C++语言可以参考GJB 8114-2013《C/C++语言编程安全子集》中的强制准则

#代码走查

代码走查和《软件测试的艺术》中代码走查基本一致。

代码走査的组织: 由四人以上组成,分别为组长、秘书、 资深程序员与专职测试人员。走査人员不能是被测试程序的编写者, 组长负责分配资料、安排计划、 主持开会, 秘书记录被发现的错误。

代码走査的过程:

a)  准备阶段:组长分发有关材料, 走査组详细阅读材料和认真研究程序 。

b)  生成实例: 走査小组人员提出一些有代表性的测试实例 。

c)  会议走査: 组长主持会议, 其他人员对测试实例用头脑来执行程序, 也就是测试实例沿程序逻辑走一通, 并由測试人员讲述程序执行过程, 在纸上或黑板上监视程序状态, 秘书记录下发现的问题。

d)  形成报告:会后将发现的错误形成报告,并交给程序开发人员。对发现错误较多或发现重大错误, 在改正错误之后再次进行会议走査 。

这种静态测试方法是一种多人一起进行的测试活动, 要求每个人尽量多提供测试实例, 这些测试实例是作为怀疑程序逻辑与计算错误的启发点, 在随测试实例游历程序逻辑时,在怀疑程序的过程中发现错误。这种方法不如代码审査检査的范围广, 错误覆盖全。

一般项目中,如果程序规模较小,一万行左右,可以考虑全部程序进行代码走查,但如果代码规模较大时,全部代码完全不切实际,应选择错误集中较多、容易出错,在程序中属于关键的函数,或者编程人员强烈建议的等,最后形成代码走查测试实例、代码走查会议记录单、走查报告等工作产品。

 

 

  • 附录A

序号

错误类型

错误清单(持续更新)

1

数据引用错误

1、是否有引用的变量未赋值或无初始化?

2、所有数组引用,是否每一个下标的值都在相应维规定的界限之内?

3、所有数组引用,是否每一个下标的值都是整数?

4、所有的通过指针或者引用变量的引用,当前引用的内存单元是否分配?(虚调用)

5、如果一个内存区域具有不同属性的别名,当通过别名进行引用时,内存区域中的数据值是否具有正确的属性?

6、变量值的类型或属性是否与编译器所预期的一致?

7、在使用的计算机上,当内存分配的单元小于内存可寻址的单元大小时,是否存在直接或间接的寻址错误?

8、当使用指针或引用变量时,被引用的内存的属性是否与编译器所预期的一致?

9、假如一个数据结构在多个过程或子过程中被引用,那么每个过程或子过程对该结构的定义是否都相同?

10、如果字符串有索引,当对数组进行索引操作或下标引用,字符串的边界取值是否有“仅差一个”的错误?

11、对于面向对象的语言,是否所有的继承需求都在实现类中得到了满足?

2

数据声明错误

1、是否所有的变量都进行了声明?

2、如果变量所有的属性在声明中没有明确说明,那么默认的属性能否被正确理解?

3、如果变量在声明语句被初始化,那么它的初始化是否正确?

4、是否每个变量都被赋予了正确的长度和数据类型?

5、变量的初始化是否与其存储空间的数据类型一致?

6、是否存在有着相似名称的变量?

3

运算错误

1、是否存在不一致的数据类型(如非运算符)的变量间的运算?

2、是否有混合模式的运算?

3、是否有相同数据结构、不同字长变量间的运算?

4、赋值语句的目标变量的数据类型是否小于右边表达式的数据类型或结果?

5、在表达式的运算中是否存在表达式向上或向下溢出的情况?

6、除法运算中除数是否为0?

7、如果计算机表达变量的基本方式是基于二进制的,那么运算结果是否不精确?例如10*0.1,在二进制计算机中,很少会等于1.0.

8、在特定场合,变量的值是否超过了有意义的范围?

9、对于包含一个以上的操作符的表达式,赋值顺序和操作符的优先顺序是否正确?

10、整数的运算是否有使用不当的情况,尤其是除法?

4

比较错误

1、是否有不同数据类型的变量之间的比较。例如将字符串与地址、日期或数字相比较?

2、是否有混合模式的比较运算,或不同长度的变量间的比较运算?

3、比较运算符是否正确?程序员经常混淆至多、至少、大于、不小于、小于和等于等比较关系

4、每个布尔表达式所叙述的内容是否都正确?例如涉及与、或、非表达式时

5、布尔运算符的操作数是否为布尔类型?比较运算符和布尔运算符是否错误地混淆在一起?

6、在二进制的计算机中,是否有用二进制表示的小数或浮点数的比较运算?

7、对于那些包含一个以上的布尔运算符的表达式,赋值顺序以及运算符的优先顺序是否正确?

8、编译器计算布尔表达式的方式是否对程序产生影响?

5

控制流程错误

1、如果程序中包含很多分支,比如有计算GO TO语句,索引变量的值是否会大于可能的分支数量?

  1. 是否所有的循环最终都终止了?

3、程序、模块或子程序是否最终都停止了?

4、由于实际情况没有满足循环的入口条件,循环体是否有可能从未执行过?

5、如果循环同时由迭代变量和一个布尔条件所控制(如一个搜索循环),循环是否越界?

6、是否存在“仅差一个”的错误,如迭代数量恰恰是多一次或者少一次?

7、如果编程语言中有语句块或代码块的概念(例如do......while或{...}),是否每一组语句都有一个明确的while语句,并且do语句也与其相应的语句对应?或者是否每一个左括号对应一个有括号?

8、是否存在不能穷尽的判断?

6

接口错误

1、被调用模块接收到的形参数量是否等于调用模块发送的实参数量?顺序是否正确?

2、实参的属性(如数据类型和大小)是否与相应形参的属性相匹配?

3、实参的量纲是否与对应形参的量纲相匹配?

4、此模块传递给彼模块的实参数量,是否等于彼模块期望的形参数量?

5、此模块传递给彼模块的实参的属性,是否与彼模块相应形参的属性相匹配?

6、此模块传递给比模块的实参的量纲,是否与彼模块相应形参的量纲相匹配?

7、如果调用了内置函数,实参的数量、属性、顺序是否正确?

8、如果某个模块或类有多个入口点,是否引用了与当前入口点无关的形参?

9、是否有子程序改变了某个原本仅为输入值得形参?

10、如果存在全局变量,在所有引用它们的模块中,它们的定义和属性是否相同?

11、常数是否以实参形式传递过?

7

输入/输出错误

1、如果对文件明确声明过,其属性是否正确?

2、打开文件的语句中各项属性的设置是否正确?

3、格式规范是否与I\O语句中的信息相吻合?

4、是否有足够的可用内存空间,来保留程序将读取的文件?

5、是否所有的文件在使用之前都打开了?

  1. 是否所有的文件在使用之后都关闭了?

7、是否判断文件结束的条件,并正确处理?

8、对I/O出错情况处理是否正确?

9、任何打印或显示的文本信息中是否存在拼写或语法错误?

10、程序是否正确处理了类似于“File Not Found”这样的错误?

8

其他检查

1、如果编译器建立了一个标识符交叉引用列表,那么对该列表进行检查,查看是否有变量从未引用过,或仅被引用过一次。

2、如果编译器建立了一个属性列表,那么对每个变量的属性进行检查,确保没有赋予过不希望的默认属性值。

3、如果程序编译通过了,但计算机提供了一个或多个“警告”或“提示”信息,应对此逐一进行认真检查。“警告”信息指出编译器对程序某些操作的正确性有所怀疑;所有这些疑问都应进行检查。“提示”信息可能会罗列出没有声明的变量,或者是不利于代码优化的用法。

4、程序或模块是否具有足够的鲁棒性?即是否对输入的合法性进行了检查?

5、程序是否遗漏了某个功能?

  • 附录B

代码审查单(可进行任意更改,仅为例子参考)

审查表名称

语言编程代码审查单

审查表标识

 

审查表描述

审查软件代码是否遵循了规定的代码规则,并审查软件代码与软件设计的符合性。

审查内容

序号

审查项

期望结果与评估标准

审查结果

通过与否

1

代码执行标准的符合性审查

寄存器使用:

1)  如果需要一个专用寄存器, 指定了吗?

2)  宏扩展或子程序调用使用了已使用着的寄存器而未保存数据吗?

3)  默认使用的寄存器的值正确吗?

 

格式:

1)  嵌套的IF 是否已正确地缩进?

2)  注释准确并有意义吗?

3)  是否使用了有意义的标号?

4)  代码是否基本上与开始时的模块模式一致?

5)  是否連循全套的编程标准?

 

入口和出口连接:

1) 初始入口的最终出口正确吗?

2) 对另一模块的每一次调用:

全部所需的参数是否已传送给每一个被调用的模块?

被传送的参数值是否正确的设置?

栈状态和指针状态是否正确?

 

程序语言的使用:

1)  模块中是否使用语言完整定义的有限子集?

2)  未使用内存的内容是否影响系统安全? 处理是否得当?

 

存储器使用:

1)  每一个域在第一次使用前正确地初始化了吗?

2)  规定的域正确吗?

3)  每个域是否由正确的变量类型声明?

4)  存储器重复使用吗?可能产生冲突吗?

 

f)  测试和转移:

l )  是否进行了浮点相等比较?

2)  测试条件正确吗?

3)  用于测试的变量正确吗?

4)  每个转换目标正确并至少执行一次?

5)  三种情况(大于 0, 小于 0, 等于 0)是否已全部测试?

 

g)  性能:

1 )  逻辑是否被最佳地编码?

2)  提供的是一般的错误处理还是异常的例程?

 

h)  可维护性:

1)  所提供的列表控制是否有利于提高可读性?

2)  标号和子程序名符合代码的意义吗?

 

i)  逻辑:

1)  每个循环是否执行正确的次数?

2)  输入参数的所有异常值是否已直接测试?

 

j) 软件多余物:

1)  是否有不可能执行到的代码?

2)  是否有即使不执行也不影响程序功能的指令?

3)  是否有未引用的变量、标号和常量?

4)  是否有多余的程序单元?

 

 

2

代码与设计的一致性和合理性审查

1)  全部设计是否均已实现?

2)  编码是否做了设计所规定的内容?

 

 

问题单标识

 

审查人员

 

监测人员

 

审查时间

 

 

猜你喜欢

转载自blog.csdn.net/weixin_31484477/article/details/81074198