|
正如大家所知道的,好的测试应具备如下的品质
§ A-TRIP(automatic,Thorough,Repeatable,Independent,Professional)
§ 自动化的:借鉴持续构建和测试的方法。参考Cruise Control
§ 彻底的:如NCover工具。
§ 可重复的:使用mock对象隔离外界因素。
§ 独立的:每个测试都有setup和tear down函数,每个测试应该是独立的孤岛,不依赖其他测试。
§ 专业的:提取公共部分。数据驱动的测试(数据与代码分离)
在用单元测试工具进行测试时,测试数据与测试程序的分离。
测试数据保存在excel中,举例如下:
fucName
expectedResult
param1
param2
param3
param4
start
1
0
0
0
0
start
-4
4
0
0
0
start
-1
0
4
0
0
SetHue
1
0
30
0
SetHue
-2
0
30
-5
SetHue
-4
4
0
0
1.1
根据经验,测试程序的颗粒划分要小,如对于同一个函数的一组非法参数的测试,要放在不同的测试程序中进行,如果一个测试程序执行了一组的,那么如有有一个非法参数失败,那么会导致其余非法参数没有运行。这样就可能需要手工屏蔽失败的非法参数,就不能实现完全的自动化。
这里,通过dll的方式导出了4个函数,这里为了清楚,把参数,返回值记录如下:
bool EnumSpecialFunction( char * functionname, std::vector<StartParameters> & result )
BOOL InitExcelObject ()
BOOL UninitExcelObject ( void )
BOOL ReadExcel ( int row, int col, char * cellmsg )
其中,EnumSpecialFunction的参数1为待测试的函数名称,如果和excel中的fucName名称相同的所有行数,都会通过参数2 result返回。例如调用EnumSpecialFunction("SetHue", data )时,参数1输入SetHue,data返回如下数据:
SetHue
1
0
30
0
SetHue
-2
0
30
-5
SetHue
-4
4
0
0
1.2
通过data【0】得到第一组数据,data【1】得到第二组数据,依此类推。
那么,如何使用导出的函数进行测试那?
第一,要将excel类添加到工程中。
在ClassWizard中,【Add Class】,在Excel的安装目录找到Excel.exe(Microsoft2003是Excel.exe;2007应该又独立的lib库,这个没有验证),添加必要的几个类:
// Excel应用对象
_Application m_oExcelApp; // Excel程序
_Worksheet m_oWorkSheet; // 工作表
_Workbook m_oWorkBook; // 工作簿
Workbooks m_oWorkBooks; // 工作簿集合
Range m_oCurrRange; // 使用区域
Worksheets m_oWorkSheets; // 工作表集合
第二,在工程下,new一个头文件,例如,命名为EnumDll,声明如下内容:
typedef struct
{
char fuctionname[50];
int expectedResult;
int a;
int b;
int c;
int d;
// int fuctionid;
}StartParameters;
BOOL InitExcelObject ( /*CString strFilePath*/ );
BOOL UninitExcelObject ( void );
BOOL ReadExcel ( int row, int col, char * cellmsg );
bool EnumSpecialFunction( char * functionname, std::vector<StartParameters> & result );
这里,用了STL(standard template library)的容器vector.
在一些使用 MFC 的程序中,经常看到许多程序使用 CArray<>,由于 CArray<>的设计问题,造成使用它的代码的复杂化,增加了维护难度。因此建议使用 ::std::vector<> 代替 CArray<>。另外,也看到一些程序在用 malloc/realloc/free/new[]/delete[] 等手工管理内存。在应用程序中,手工管理内存是容易导致错误的,应该用 ::std::vector<> 之类的对象来管理动态数组。如果用数组的话,需要手动释放,vector的话,不是指针的,就会自己在析构函数中释放.所以这里用了vector。个人比较喜欢用STL提供的容器,记得使用时,添加对应的头文件啊。这里不详细介绍了。
第三,在工程的头文件中,需要添加:
#include <vector>
#include "..\EnumDll.h"
第四,在工程路径下,copy dllEnumSpecialFunction.lib与dllEnumSpecialFunction.dll,并新建一个名称为Demo.xls的excel文件作为测试程序要读取的测试数据,格式如1。1所示。在project setting\link下把dllEnumSpecialFunction.lib添加进来。
第五,在cppunit的测试框架下,当然,其他测试框架也可以,在测试程序中,在setUp函数中,调用dll导出的函数EnumSpecialFunction,这里函数名称为start,如下代码:
char functionname[] = "start";
void SampleTest::setUp()
{
EnumSpecialFunction( functionname, data );
}
在要测试start函数的testcase中,如testStart1函数中,调用如下即可:
void SampleTest::testStart1()
{
int resstart = 0;
StartParameters startparam = data[0];
resstart = start( startparam.a, startparam.b, startparam.c, startparam.d );
CPPUNIT_ASSERT( startparam.expectedResult==resstart );
}
类似,可以通过给EnumSpecialFunction函数输入不同的函数名称测试不同的函数,通过data[0],data[n]来选择执行excel中的某组测试。
如果有人需要dll,可以留言,我会发给大家啊。别担心,完全免费的!!
另,该dll也提供了write excel的函数,来写测试报告到excel中。
下篇将详细介绍基于cppunit的测试报告在excel的生成,也是基于我写的dll的哦。
测试报告的生成 收藏
dll除了导出上篇测试程序通过excel读取测试数据达到数据与程序的分离,所说的这几个函数来实现测试数据写到excel中,从而实现测试数据与测试程序分离外,输出函数如下:
BOOL InitExcelObject ( /*CString strFilePath*/ );
BOOL UninitExcelObject ( void );
BOOL ReadExcel ( int row, int col, char * cellmsg );
bool EnumSpecialFunction( char * functionname, std::vector<StartParameters> & result );
还导出了BOOL WriteExcel ( CString funcName, CString funcResult, int sorceline, CString failInfor );
用于向excel中写测试报告。
那么,如何使用导出的函数进行测试那?请参考上篇测试程序通过excel读取测试数据达到数据与程序的分离。
注意:测试报告的生成到excel中,当前工作路径下,需要新建一个名为TestReport.xls的excel。
本次工程是基于cppunit这个框架,cppunit所提供的断言,如CPPUNIT_ASSERT(condition);如果失败,则本testcase后其他断言不再运行,退出本次testcase,继续执行其他testcase。鉴于此,涉及程序如下:
void SampleTest::testStart1()
{
EnumSpecialFunction( functionname, data );
int resstart = 0;
StartParameters startparam = data[0];
resstart = start( startparam.a, startparam.b, startparam.c, startparam.d );
//以上程序使用了从excel读取测试数据的方法,详细参考上篇
char funName[] = "testStart1";
int line = CPPUNIT_SOURCELINE().lineNumber();//这里参考了cppunit提供的方法,可以获取当前的行号。
MY_CPPUNIT_ASSERT( funName, line, startparam.expectedResult==resstart );//这里是自己重新实现的断言,就不再使用cppunit的断言了
//Many Assert,这里会有很多其他待测试函数的判断的断言,如果任意一个断言失败,都直接跳出当前的testStart1的执行,所以所有断言都通过,才会继续进行,所以运行到这里,说明本testStart1中的测试程序都成功了,直接给dll提供的函数传入正确的参数:funcResult中传入"Pass", line传入-1,具体如下:
CString errInfor;
errInfor.Format("%d", 0);
WriteExcel ( funName, "Pass", -1, errInfor );
}
重新写cppunit的断言如下:
#define MY_CPPUNIT_ASSERT( funName, line, condition )\
CString infor = #condition; \
if ( !(condition) ) \
{ \
if( line > 0 )\
{\
WriteExcel ( funName, "Fail", line, infor );\
}\
} \
CPPUNIT_ASSERT(condition);//这里调用cppunit中提供的断言。
需要参考程序或者dll的话,可以留言,免费提供的哦~~ |
|