下面是单元测试类的定义:
#if !defined(DISKDATA_TESTCASE_H_INCLUDED)
#define DISKDATA_TESTCASE_H_INCLUDED
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include <cppunit/TestCase.h>//为了从基类TestCase派生新的测试类
#include <cppunit/extensions/HelperMacros.h>//方便快速定义测试类的宏
#include "DiskData.h"
class DiskDataTestCase : public CppUnit::TestCase
{
CPPUNIT_TEST_SUITE(DiskDataTestCase);//定义Test Suite的起点
CPPUNIT_TEST(loadTest);//定义Test Case
CPPUNIT_TEST(storeTest);
CPPUNIT_TEST_SUITE_END();//定义Test Suite的终点
public:
void setUp();
void tearDown();
protected:
void loadTest();
void storeTest();
private:
DiskData *fixture;
};
#endif
例程中,DiskDataTestCase类重载了两个方法:setUp()和tearDown()。这两个方法在Test Case开始和结束的时候自动运行。
测试逻辑是在两个Protected方法中实现的,稍后要涉及到如何为测试逻辑编码。
例程的后定义了指向DiskData类型数据的指针fixture,用以保存测试过程中的目标对象。setUp()是初始化函数,在调用每一个Test Case之前调用setUp(),同时负责初始化目标对象。Test Case运行过程中要使用fixture。在每一个Test Case运行结束之后,调用tearDown()销毁fixture。这样,每次运行Test Case时所使用的都是新产生的fixture。
测试步骤如下:
开启测试程序
点击“Run”按键
调用setUp()方法:初始化fixture
调用第一个Test Case函数
调用tearDown()方法:释放fixture
调用setUp()方法:初始化fixture
调用第二个Test Case函数
调用tearDown()方法:释放fixture
...
经过编码:
#include "DiskDataTestCase.h"
CPPUNIT_TEST_SUITE_REGISTRATION(DiskDataTestCase);
void DiskDataTestCase::setUp()
{
fixture = new DiskData();
}
void DiskDataTestCase::tearDown()
{
delete fixture;
fixture = NULL;
}
void DiskDataTestCase::loadTest()
{
// our load test logic
}
void DiskDataTestCase::storeTest()
{
// our store test logic
}
现在,编码已经变得非常简单了:setUp()和tearDown()实现了创建、释放fixture,下面要做的是为loadTest()、storeTest()编码了。
Test Case编码
搞清楚需要测试那些方面之后的工作是编码实现。可以通过使用库函数、第三方库函数、Win32 API或者C/C++操作符和指令的内部属性。
有时需要辅助的文件或者数据库表来存储正确的数据。在本例中,通过对比内部不数据和外部文件的数据来判断结果是否正确。
当出现错误时(比如内部数据和外部数据不同),需要抛出异常。可以通过CPPUNIT_FAIL(message)宏实现,也可以通过assertions宏实现。
以下是一些常用的assertion宏:
CPPUNIT_ASSERT(condition): 检查condition,如为false,抛出异常
CPPUNIT_ASSERT_MESSAGE(message, condition): 检查condition,如为false,抛出异常,并显示预先设定的信息
CPPUNIT_ASSERT_EQUAL(expected,current): 检查expected与current的值是否相等,抛出异常,显示expected和current的值
CPPUNIT_ASSERT_EQUAL_MESSAGE(message,expected,current): 检查expected的值与actual的值是否相等,抛出异常,显示expected,current的值,并显示预先设定的信息
CPPUNIT_ASSERT_DOUBLES_EQUAL(expected,current,delta): 检查expected, current之差是否小于delta,如果不小于,显示expected和current的值
下面讲一下loadTest编码的编码构想:首先需要一个外部文件,其中存储这一个DATA型数据,文件的创建方式并不重要,关键是要保证里面的数据的正确性。然后,要进行的操作是检查load函数从外部文件中读出的数据和实现存在其中的数据是否一致。代码如下:
//
// 前提:外部文件中已存储了正确的数据。
//
#define AUX_FILENAME "ok_data.dat"
#define FILE_NUMBER 19
#define FILE_STRING "this is correct text stored in auxiliar file"
void DiskDataTestCase::loadTest()
{
// 相对路径转化为路径
TCHAR absoluteFilename[MAX_PATH];
DWORD size = MAX_PATH;
strcpy(absoluteFilename, AUX_FILENAME);
CPPUNIT_ASSERT( RelativeToAbsolutePath(absoluteFilename, &size) );
// 执行操作
CPPUNIT_ASSERT( fixture->load(absoluteFilename) );
// 通过assertion检查运行结果
LPDATA loadedData = fixture->getData();
CPPUNIT_ASSERT(loadedData != NULL);
CPPUNIT_ASSERT_EQUAL(FILE_NUMBER, loadedData->number);
CPPUNIT_ASSERT( 0 == strcmp(FILE_STRING,
fixture->getData()->string) );
}