今天主要讲解“软件的白盒测试”第一部分,之前我们详细介绍了测试用例的设计方法,这些测试用例的设计方法主要是针对黑盒测试进行的。而一个完整的软件测试过程包括界面和代码两部分的测试,本章主要介绍基于代码的测试方法,即单元测试,也可以称为白盒测试。
本章主要包括以下内容:
单元测试介绍
静态测试技术
动态测试技术
CppUnit自动化单元测试框架
一、单元测试介绍
单元测试主要是对单元测试的基础知识进行介绍,包括单元测试的定义、单元测试对象、单元测试环境和单元测试策略。
1、单元测试定义
单元测试是对软件基本组成单元进行的测试,如函数(function、procedure)或一个类的方法(method)。单元具有一些基本属性,如明确的功能、规格定义、与其他部分的接口定义等,可清晰地与同一程序的其他单元划分。
在一种传统的结构化编程语言(比如C 语言)中,要进行测试的单元一般是函数或子过程。在类似C++这样的面向对象的语 言中,要进行测试的基本单元是类或类的方法。测试时基本单元不一定是指一个具体的函数或一个类的方法,也可能对应多个程序文件中的一组函数。
单元测试的目的在于发现各模块内部可能存在的各种错误,主要包括以下几个方面:
(1)验证代码是与设计相符合的。
(2)发现设计和需求中存在的错误。
(3)发现在编码过程中引入的错误。
2、单元测试的重点
单元测试主要是针对系统最基本的单元代码进行测试,测试时主要从接口、独立路径、出错处理、边界条件和局部数据五个方面进行测试,如图10-1 所示。通过这五个方面来检查模块内部是否存在错误。
图10-1 单元测试重点
下面就这五个方面进行详细的介绍。
(1)接口测试。
接口测试主要是对函数数据的输入和输出进行测试,主要包括以下几个方面的内容:
1)调用所测模块时的输入参数与模块的形式参数在个数、属性、顺序上是否匹配。
2)所测模块调用子模块时,它输入给子模块的参数与子模块中的形式参数在个数、属性、顺序上是否匹配。
3)是否修改了只用作输入的形式参数。
【实例】形式变量sum 被作为工作变量使用,当外部函数调用该函数时,外部变量很可能会覆盖该形式参数对应的内存区域,进而导致sum 的结果不一致。
void sum_data( unsigned int num, int *data, int *sum )
{
unsigned int count;
*sum = 0;
for (count = 0; count < num; count++)
{
*sum += data[count]; // sum 成了工作变量
}
}
应该将以上代码进行修改,修改后的代码如下:
void sum_data( unsigned int num, int *data, int *sum )
{
unsigned int count ;
int sum_temp;
sum_temp = 0;
for (count = 0; count < num; count ++)
{
sum_temp += data[count];
}
*sum = sum_temp;
}
4)输出给标准函数的参数在个数、属性、顺序上是否正确。
5)全局变量的定义在各个模块中是否一致。
6)约束条件是否通过形式参数来传送。
如果约束条件通过形式参数来传送,很容易出现控制耦合的情况,如以下代码段:
int add_sub( int a, int b, unsigned char add_sub_flg )
{
if (add_sub_flg == integer_add)
{
return (a + b);
}
else
{
return (a – b);
}
}
可以将代码分成两个函数来实现,代码如下:
int add( int a, int b )
{
return (a + b);
}
int sub( int a, int b )
{
return (a – b);
}
关于耦合还有以下几种情况:
1)无直接耦合:两个模块之间没有直接的调用关系,称为无直接耦合。
2)数据耦合:如果两个模块之间只是通过参数交换信息,而且所交换的信息仅仅是简单数据类型,那么这种耦合称为数据耦合。
3)印记耦合:如果数据结构作为参数进行传递,就称为印记耦合。印记耦合是数据耦合的一个变种。
4)控制耦合:如果两个模块之间所交换的信息包含控制信息,那么这种耦合称为控制耦合。
5)外部耦合:如果某个模块和外部的硬件环境产生交互操作,则产生外部耦合。
6)共用耦合:当两个或多个模块通过一个公共区相互作用时,它们之间的耦合称为共用耦合。
这类公共区可以是全程数据区、共享通信区、内存公共覆盖区、任何介质上的文件、物理设备等。
7)内容耦合:内容耦合指的是一个模块和另外一个模块的内容直接产生联系,一个模块直接转移到另一个模块内部,一个模块使用另一个模块的内部数据,都会产生内容耦合。内容耦合是最高程度的耦合,是应该避免的。
(2)独立路径测试。
独立路径主要测试程序的运行路径是否存在错误,对基本执行路径和循环进行测试容易发现大量的错误,设计测试用例查找由于错误的计算、不正确的比较或不正常的控制流而导致的错误。主要包括以下几个方面的内容:
1)运算的优先次序不正确或误解了运算的优先次序:如+和-运算符的优先级高于>>和<<操作符。
2)运算的方式错误:如本来希望a=++b,而错误地写成了a=b++。
3)不同数据类型的比较:如a 为unsigned 类型,b 为int 类型,执行while(a>b)语句时很容易出现死循环,因为a 为无符号类型。
4)“差1 错”,即循环的次数多了一次或少了一次:如for(i=0;i<=100;i++),本来只希望循环100 次,结果循环了101 次。
5)错误的或不可能的循环终止条件:如while(|a|<0)这个条件永远不可能正确。
6)关系表达式中不正确的变量和比较符:如将等号写成了赋值符,if(a==1)写成了if(a=1)。
7)当遇到发散的迭代时不能终止循环。
8)循环变量修改错误:while(i) {循环体中错误地修改i 的值,使得循环次数错误}。
(3)出错处理测试。
比较完善的单元设计要求能预见出错的条件,并设置适当的出错处理,以便在程序出错时,能对出错程序重新做安排,保证其逻辑上的正确性。
主要包括以下几个方面的内容:
1)出错的描述难以理解:如用户登录失败提示“Error code001”,该提示信息不易理解。
2)出错的描述不足以对错误定位和确定出错的原因:如网络无法连接时,提示“网络连接失败”。
3)显示的错误与实际的错误不符:如用户名输入错误时,提示“密码错误”。
4)对错误条件的处理不正确:如注册邮箱,提示输入的用户名格式错误,但还能正确地注册一个账号。
5)在对错误进行处理之前,错误条件已经引起系统的干预等。
(4)边界条件测试。
边界条件测试主要测试函数对循环条件、控制条件、数据流等临界值的处理情况,主要包括以下几个方面的内容:
1)在n 次循环的第n 次,取最大值或最小值时容易发生错误。
2)特别要注意数据流、控制流中等于、大于、小于确定的比较值时出现错误的可能性。
(5)局部数据结构测试。
局部数据结构测试主要测试对数据定义是否存在错误,包括以下几个方面的内容:
1)检查不正确或不一致的数据类型说明:如将a 的类型设置为unsighed int 类型,如果将a<0设置为结束的条件,那么一定会进入死循环,因为a 永远不可能为负数。
2)使用尚未赋值或尚未初始化的变量。
3)错误的初始值或错误的缺省值:如int a=65536,会导致a 实际的值为0。
4)变量名拼写错误或书写错误。
5)不一致的数据类型:如int a 和float b,如果运行a=b,那么会导致精度丢失。
本章节关于“软件的白盒测试”的第一部分就学习到这里,大家觉得文章有用的话记得每天来这里和小编一起学习涨薪技能哦。