陕西凌云电器集团有限公司设计所 魏银英 杨 苗
随着软件系统越来越复杂,在产品开发各阶段进行完全的软件测试也越来越重要,大多数软件开发者都已意识到这一点。但考虑到测试费用问题,软件开发者往往面临着在提高产品质量与减少费用之间进行选择的问题。IPL提供的Cantata测试软件应这种需要,在合理的费用下提供给软件开发者的强有效的软件测试工具。Cantata可以同时支持C和C++语言的测试,能够满足开发者进行高效的单元和集成测试的需求,该产品不仅能提高产品质量,还能帮助提高生产率。
作为专业软件测试工具,Cantata++除包含一些标准的特征之外,还提供了一些新功能:
(1)支持语句、判定和布尔代码覆盖率度量;
(2)支持运用白盒测试技术,自动获取私有类数据;
(3)支持面向对象测试用例的重用;
(4)图形化和XML形式的结果报告。[1]
软件质量的好坏很大程度上取决于测试用例的设计质量。不论程序员的编程水平、软件设计水平有多高,软件工程化执行得多好,如果没有通过合适质量的测试用例进行测试,其最终软件质量都是难以保证的。因此,测试用例设计是软件测试的最核心和最重要的内容之一。[2]
单元测试主要使用白盒测试技术,测试用例的设计方法一般分两种类型,即测试人员自己编写测试脚本和借助测试工具生成测试脚本框架后维护测试数据。Cantata++测试工具可用于生成和维护测试脚本,编译并运行测试可执行程序,查看测试结果和覆盖率数据。
在cantata工具中常见的单元测试用例的实现方法很简单,不再赘述。本文主要介绍复杂函数实现的单元测试用例的设计方法。如单元测试的被测单元函数使用的函数形参是结构体变量和全局变量是结构体数组且结构体的成员是指针时,在设计测试用例时如何给结构体变量赋值?
Cantata测试工具自动生成的测试用例中,函数形参的默认值都是“NOT_SET”,编译测试脚本时不能被识别,给函数的形参赋正确的参数值是得到正确的测试结果的前提。设计带有结构体类型的形参的测试用例时,我们分别做了如下实验:
(1)按照在C语言中结构体变量成员赋值的方式给测试用例中的结构体变量赋值;
(2)使用改造C语言结构体变量成员赋值的方式把“->”改为“·”给测试用例中的结构体变量赋值。
编译结果证明两种赋值方式均不能被正确识别。
Cantata在自动生成测试用例时使用其本身封装的INITIALISE()函数给全局变量赋初值为0x55,以满足一般的测试需要。为达到充分测试的目的,需要给全局变量赋相应的数值,当全局变量为结构体类型的数组变量,且其成员为指针时,我们进行了如下实验:
(1)使用C语言中数组初始化的方式给结构体数组赋值;
(2)一个数组元素一个数据元素的方式给结构体数组赋值;
(3)使用分配内存的方式给结构体数组赋值。
编译结果证明三种赋值方式均不能被编译器识别。
结构体形参赋值时是不是因为该形参在赋值之前没有被分配内存空间所以无法赋值?结构体数组赋值的情况会不会因为cantata测试工具对编码规则要求较严格,必须按照相应的编程规则才可以编译通过?带着这种疑问我们查阅了大量编程规则的资料,通过反复实践,最终找到了解决该两个问题的办法。
其一,假设函数形参是如下两个结构体变量:
struct DIST* StrCount;
struct FILTER* StrFilter;
在测试用例脚本中可以通过下面的方式给结构体变量赋值:
StrCount = malloc(sizeof(struct DIST));
StrFilter = malloc(sizeof(struct FILTER));
memset(DIST_COUNT,0,sizeof(struct DIST));
memset(DIST_FILTER,0,sizeof(struct FILTER));
StrCount->cnt = 100; /*结构体成员赋初值*/
free(StrCount) ;
free(StrFilter) ;/*释放内存*/
如此赋值后的测试脚本文件加入测试工程后编译通过,得到了覆盖率测试结果,函数形参是结构体类型变量的测试用例设计的问题得以解决。
其二,假定定义如下的结构体数组:
PORT_CB g_PortCbTable[10];
其中:PORT_CB 为如下的结构体类型:
typedef struct
{
char num[16]; /* 端口名称*/
CONNOBJ* pObj; /* 端口句柄指针*/
}PORT_CB;
在测试用例脚本中,修改指针成员变量的方式为:
g_PortCbTable[0].pObj = (CONNOBJ*)-1;
g_PortCbTable[1].pObj = (CONNOBJ*)1U;
g_PortCbTable[2].pObj = (CONNOBJ*)1U;
g_PortCbTable[3].pObj = (CONNOBJ*)1U;
g_PortCbTable[4].pObj = (CONNOBJ*)1U;
g_PortCbTable[5].pObj = (CONNOBJ*)-12;
g_PortCbTable[6].pObj = (CONNOBJ*)2U;
g_PortCbTable[7].pObj = (CONNOBJ*)2U;
g_PortCbTable[8].pObj = (CONNOBJ*)2U;
g_PortCbTable[9].pObj = (CONNOBJ*)2U;
其中有后缀U或无后缀指明所赋常量的类型,强制转换类型不可以忽略。如此赋值后的测试脚本文件加入测试工程后编译通过,得到了覆盖率测试结果,至此全局变量为结构体类型的数组变量,且其成员为指针时,测试用例的设计问题得以解决。
本文介绍了测试工具cantata的功能特性及其在单元测试中的应用,在此基础上提出了一种复杂单元函数的测试用例设计方法,该方法在类似的软件测试项目中得到了应用,在实践中取得了良好效果。
[1]Cantata++ Reference Manual v6.1 2011,3.
[2]周伟明著.软件测试实践[M].电子工业出版社,2008:46.