一、静态分析工具
静态分析程序不需要执行所测试的程序,它扫描所测试程序的正文,对程序的数据流和控制流进行分析。然后送出测试报告。通常,它具有以下几类功能:
(1)对模块中的所有变量,检查其是否都已定义,是否引用了未定义的变量,是否有已赋过值但从未使用的变量。实现方法是建立变量的交叉引用表。
(2)检查模块接口的一致性。主要检查子程序调用时形式参数与实际参数的个数、类型是否一致,输入输出参数的定义/使用是否匹配、数组参数的维数、下标变量的范围是否正确,各子程序中使用的公用区(或外部变量、全局变量)定义是否一致等等。
(3)检查在逻辑上可能有错误的结构以及多余的不可达的程序段。如交叉转入转出的循环语句,为循环控制变量赋值,存取其他模块的局部数据等。
(4)建立“变量/语句交叉引用表”、“子程序调用顺序表”、“公用区/子程序交叉引用表”等。利用它们找出变量错误可能影响到哪些语句,影响到哪些其他变量等。
(5)检查所测程序违反编程标准的错误。例如,模块大小、模块结构、注释的约定、某些语句形式的使用,以及文档编制的约定等。
(6)对一些静态特性的统计功能:各种类型源语句的出现次数,标识符使用的交叉索引,标识符在每个语句中使用的情况,函数与过程引用情况,任何输入数据都执行不到的孤立代码段,未经定义的或未曾使用过的变量,违背编码标准之处,公共变量与局部变量的各种统计。
静态分析工具的结构一般由四部分组成:语言程序的预处理器、数据库、错误分析器和报告生成器。预处理器把词法分析与语法分析结合在一起,以识别各种类型的语句。源程序被划分为若干程序模块单元(如主程序与一些子程序),同时生成包含变量使用、变量类型、标号与控制流等信息的许多表格。有些表格是全局表,它们反映整个程序的全局量信息,如模块名、函数及过程调用关系、全局量等。有些表格是局部表,它们对应到各个模块,记录模块中的各种结构信息,如标号引用表、分支索引表、变量属性表、语句变量引用、数组或记录特性表等。中国自学编程网整理发布所有表格都存入数据库。不少测试工具有专门设计来存放各种信息的数据库,通常以命令语言的形式来作为查询语言。也有使用商用数据管理系统的。错误分析器在用户指导下利用命令语言或查询语言与系统通信进行查错。并把检查结果造表输出。
二、动态测试工具
动态测试就是通过选择适当的测试用例,实际运行所测程序,比较实际运行结果和预期结果,以找出错误。动态测试分为结构测试与功能测试。在结构测试中常采用语句测试、分支测试或路径测试。作为动态测试工具,它应能使所测试程序有控制地运行,自动地监视、记录、统计程序的运行情况。典型方法是在所测试程序中插入检测各语句的执行次数、各分支点、各路径的探针(probe),以便统计各种覆盖情况。有些程序设计语言的源程序清单中没有标号,在进行静态分析或动态测试时,还要重新对语句进行编号,以便能标志各分支点和路径。在有些程序的测试中,往往要统计各个语句执行时的cPU时间,以便对时间花费最多的语句或程序段进行优化。
(1)测试覆盖监视程序
主要用在结构测试中,可以监视测试的实际覆盖程度。主要的工作有:分析并输出每一可执行语句的执行特性;中国自学编程网整理发布分析并输出各分支或各条路径的执行特性;计算并输出程序中谓词的执行特性;为此,测试覆盖监视程序的工作过程分为以下三个阶段:
1)对所测试程序做预处理。如在程序的分支点和汇合点插入“执行计数探针”;在非简单赋值语句(相对于赋常数值或下标计算等简单赋值语句而言)后插入“记忆变量值探针”,记录变量的首次赋值、末次赋值、最小值、最大值。以及在循环语句中插入“记忆控制变量值探针”,记录循环控制变量的首次赋值、末次赋值、最小值、最大值。
2)编译预处理后的源程序,运行目标程序。在运行过程中,利用探针,监视、检查程序的动态行为,收集与统计有关信息。
3)一组测试后,可以根据要求,输出某一语句的执行次数,某一转移发生的次数,某赋值语句的数值范围,某循环控制变量的数据范围,某子程序运行的时间、所调用次数等。从而发现在程序中从未执行的语句,不应该执行而实际执行了的语句,应该执行但实际没有执行的语句,以及发现不按预定要求终止的循环、下标值越界、除数为零等等异常情况。
(2)断言处理程序
“断言”是指变量应满足的条件。例如,I<10,A(6)>O等。在所测试源程序中,在指定位置按一定格式,用注释语句写出的断言叫做断言语句。在程序执行时,对照断言语句检查事先指定的断言是否成立。可以帮助复杂系统的检验、调试和维护。
断言分局部性断言和全局性断言两类。局部性断言,是指在程序的某一位置上,例如,重要的循环或过程的入口和出口处,或者在一些可能引起异常的关键算法之前设置的断言语句。例如在赋值语句A—B/z之前,设置局部性断言语句:
C ASSERT L()CAL(Z<>O)
全局性断言,是指在程序运行过程中自始至终都适用的断言。例如,变量I、J、K只能取O到100之间的值,变量M、N只能取2、4、6、8四个值等。全局性断言写在程序的说明部分。描述格式为
C ASSERT VALUES(I,J,K)(O:100)
C ASSERT VALUES(M,N)(2,4,6,8)
程序员在每个变量、数组的说明之后,都可写上反映其全局特性的断言。
动态断言处理程序的工作过程如下:
1)动态断言处理程序对语言源程序做预处理,为注释语句中的每一个断言插入一段相应的检验程序。
2)运行经过预处理的程序,检验程序将检查程序的实际运行结果与断言所规定的逻辑状态是否一致。对于局部性断言,每当程序执行到这个位置时,相应的检验程序就要工作;对于全局性断言,在每次变量被赋值后,相应的检验程序就进行工作。
动态断言处理程序还要统计检验的结果(即断言成立或不成立的次数),在发现断言不成立的时候,还要记录当时的现场信息,如有关变量的状态等。处理程序还可按测试人员的要求,在某个断言不成立的次数已达指定值时中止程序的运行,并输出统计报告。[Page]
3)一组测试结束后,程序输出统计结果、现场信息,供测试人员分析。
(3)符号执行程序
符号执行法是一种介于程序测试用例执行与程序正确性证明之间的方法。它使用了一个专用的程序,对输入的源程序进行解释。在解释执行时,所有的输入都以符号形式输入到程序中,这些输入包括基本符号,数字及表达式等。符号执行的结果,可以有两个用途:其一是可以检查公式的执行结果是否达到程序预期的目的;其二是通过程序的符号执行,产生程序的路径,为进一步自动生成测试数据提供条件。
解释程序在对象源程序的判定点计算谓词。一个条件语句if……then…else的两个分支在一般情况下需要进行并行计算。语法路径的分支形成一棵“执行树”,树中每一个结点都是一个
表示执行到该结点时累加判定的谓词。一旦解释程序对对象源程序的每一条语法路径都进行了符号计算,就会对每一条路径给出一组输出,它是用输
入再加上遍历这条路径所必须满足的条件的谓词组这两者的符号形式表示的。实际上,这种输出包含了程序功能的定义。在理想情形下,这种输出可以自动地与可用机器执行的程序所要具备的功能进行比较。否则可用手工进行比较。由于语法路径的数目可能很大,再加上其中有许多是不可达路径,这时可对执行树进行修剪。但是修剪时必须特别小心,不要把“重要”路径无意中修剪掉。另外,还有一个问题:如果对象源程序中包含有一个循环,而循环的终止取决于输入的值,那么执行树就会是无穷的,这时,必须加以人工干预,进行某种形式的动态修剪,以恢复解释执行。
符号执行更有用的一个结果是用于产生测试数据。符号执行的各种语法路径输出的累加谓词组(只要它是可解的)定义了一组等价类,每一等价类又定义了遍历相应路径的输出,可依据这种信息来选择测试数据。寻找好的测试数据就等于寻找语义(即可达)路径,中国自学编程网整理发布它属于语法路径的子集,因此,可依据这种信息来选择测试数据。
符号执行方法还可以度量测试覆盖程度。如果路径谓词的析取值为真(true),则该测试用例的集合就“覆盖”了源程序。如果不是这样,该析取值的取假(false),表示源程序有没有测试到的区域。
4)除了覆盖分析这个最重要的特性外,下列动态特性也经常作为测试的结果予以分析
1)调节分析:确定所测程序哪些部分执行次数最多,哪些部分执行次数最少,甚至未执行过。
2)成本估算:确所测程序哪些部分执行开销最大。
3)时间分析:报告某一程序或其部分程序的cPu执行时间。
4)资源利用:分析与硬件和系统软件相关的资源利用情况。