CppUnit是一个非常优秀的开源测试框架,主要功能就是对单元测试进行管理,并可进行自动化测试。
用CppUint进行测试时,一般先以某个函数或者某个类作为测试单元,完成测试;在完成这些基本的测试后,再将引用到测试过的这些函数或者类的函数或者类,左为测试单元完成测试;继续下去,从而完成整个模块甚至是整个系统的测试,从而达到更多清除bug的目的。
测试中,始终以功能代码为主要测试对象,对GUI部分太弱。
CppUint进行测试的基本原理是:对于每一批测试,编写一个继承自TestFixture的测试类,其中setUp和tearDown 两个虚函数分别用于进行测试数据的初始化和释放操作;对于每一项测试,分别定义一个void返回类型的无参数方法,检测测试过程,可以用以下几个宏:
CPPUNIT_ASSERT(condition) |
断言condition为真,否则失败 |
CPPUNIT_ASSERT_MESSAGE(message,condition) |
当condition为假时失败, 并打印message |
CPPUNIT_FAIL(message) |
当前测试失败, 并打印message |
CPPUNIT_ASSERT_EQUAL(expected, actual) |
确信两者相等,否则失败 |
CPPUNIT_ASSERT_EQUAL_MESSAGE(message, expected, actual) |
确信两者相等,否则失败,并同时打印message |
CPPUNIT_ASSERT_DOUBLES_EQUAL(expected, actual, delta) |
当expected和actual之间差大于delta时失败 |
其中,“失败”的含义就是程序运行出现异常,并且所有测试过程中止。
在完成一个或者多个测试类的编写后,需要用TestRunner类的实例来运行每个测试类的测试函数进行测试。TestRunner类型共有:TextUi::TestRunner,QtUi::TestRunner,MfcUi::TestRunner三个,都可以用来运行测试,其区别为:
TextUi::TestRunner |
默认将信息输出到控制台,也可以指定输出到std::ostringstream。 |
QtUi::TestRunner |
用QT的GUI输出信息 |
MfcUi::TestRunner |
用MFC的GUI输出信息 |
整个测试过程需要另外附加代码,所以通常情况下,测试用例代码和被测试对象因在不同的项目中。应该在另一个项目(最好在不同的目录)中编写测试类,然后把被测试的对象包含在测试项目中。根据测试工程建立的类型,Consol可以选择TextUi::TestRunner,将结果输出至控制台显示,MFC的GUI可以使用MfcUi::TestRunner,使用GUI来控制并查看测试结果。测试工程与被测试对象所在工程的类型是可以不同的。
在使用VC作为开发工工具时,建议使用TextUi::TestRunner,并更改其Outputter实例,使用附加的TraceOutputter,将信息输出到信息输出栏,双击信息输出栏中一行,即可定位到出错位置。
以VC使用为例,步骤如下:
1. 获取原始包,比如cppunit-1.10.2.rar,解压缩到某个目录,比如d:\cppunit-1.10.2
2. 打开VC,菜单Tools -> Options,在Options对话框的Directories页中,include Files添加“d:\cppunit-1.10.2\include”,Library Files添加“d:\cppunit-1.10.2\lib”。
3. 打开工程d:\cppunit-1.10.2\src\CppUnitLibraries.dsw,在该工程中,cppuint是静态库版本,cppunit_dll是动态库版本,一般只需要完成release版本编译,如果想要研究源代码,可以考虑编译debug版本,用于调试和跟踪代码。
4. 如要使用MfcUi::TestRunner,编译dsplugin工程和TestRunner工程。dsplugin是一个VC的插件,TestRunner就是MfcUi::TestRunner的实现。
建立一个简单的安装包,将需要的文件和配置等,自动完成拷贝和添加,供开发人员使用。
所有人使用同一个编译版本,避免不必要的麻烦。
步骤如下:
1. 包含文件#include <cppunit/extensions/HelperMacros.h>
2. 声明一个类,比如,CMyTestFixture,继承自CppUnit::TestFixture。
3. 声明setUp和tearDown函数。
4. 声明测试函数,比如RunTestFunc,
5. 如果含有其他测试函数,继续添加。
6. 在类声明部分添加如下宏,声明改类为测试类,并且声明那些函数为测试函数
CPPUNIT_TEST_SUITE( CMyTestFixture);
CPPUNIT_TEST( RunFunc );
CPPUNIT_TEST_SUITE_END();
7. 最后在实现的CPP文件中,添加下面的宏,用于注册测试类到某个测试项目,比如以"MyTest"命名的项目。
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( CMyTestFixture, "MyTest" );
8. 实现setUp和tearDown,以及各个测试函数。
下面是一个例子的头文件
#include <cppunit/extensions/HelperMacros.h> class CMyTestFixture : public CppUnit::TestFixture { CPPUNIT_TEST_SUITE( CMyTestFixture ); CPPUNIT_TEST( RunTestFunc); CPPUNIT_TEST_SUITE_END(); public: CMyTestFixture(); virtual ~CMyTestFixture(); virtual void setUp(); virtual void tearDown(); void RunTestFunc(); }; |
下面是实现文件内容
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( CMyTestClass, "MyTest" );
CMyTestFixture::CMyTestFixture() { …… } CMyTestFixture::~CMyTestFixture() { // …… } void CMyTestFixture::setUp() { // …… } void CMyTestFixture:: tearDown() { // …… } void CMyTestFixture::RunTestFunc() { // …… CPPUNIT_ASSERT_MESSAGE( "Error Here", 0); // …… } }; |
以控制台中运行为例,步骤如下:
1. 包含头文件#include <cppunit/extensions/TestFactoryRegistry.h>
2. 包含TextUi::TestRunner的头文件#include <cppunit/ui/text/TestRunner.h>
3. 定义TestRunner的实例:CppUnit::TextUi::TestRunner runner;
4. 根据项目命名,得到某个项目的实例:
CppUnit::TestFactoryRegistry ®istry =
CppUnit::TestFactoryRegistry::getRegistry("MyTest");
5. 将测试内容添加到TestRunner实例中:runner.addTest( registry.makeTest());
6. 运行测试:runner.run();
如下,就是一个例子代码:
#include <cppunit/extensions/TestFactoryRegistry.h> #include <cppunit/ui/text/TestRunner.h>
int main(int argc, char* argv[]) { CppUnit::TextUi::TestRunner runner;
CppUnit::TestFactoryRegistry ®istry = CppUnit::TestFactoryRegistry::getRegistry("MyTest"); runner.addTest( registry.makeTest()); runner.run();
return 0; } |
以及其运行后的效果:
根据框中所显示的内容,可以知道在什么位置,测试失败了。
如果要输出到VC的输出窗口,对控制台中的代理做如下修改:
1. 再添加一个包含的头文件#include <cppunit/TraceOutputter.h>
2. 在进行步骤6运行测试前,添加如下代码
runner.setOutputter( new CppUnit::TraceOutputter( runner.result()));
部分修改后的代码如下:
runner.addTest( registry.makeTest()); runner.setOutputter( new CppUnit::TraceOutputter( runner.result())); runner.run(); |
根据框中所显示的内容,可以知道在什么位置,并且直接双击该行,直接定位到相应代码。使用时一定要注意,如果使用该模式,只能在Windows下使用,必须在#include <cppunit/TraceOutputter.h>前一定要先#include <windows.h>。
如果使用MfcUi::TestRunner,对控制台中的代理做如下修改:
1. 步骤2中包含TextUi::TestRunner的头文件改成包含MfcUi::TestRunner的头文件
#include <cppunit/ui/MFC/TestRunner.h>
2. 步骤3定义TestRunner的实例的代码改成:CppUnit::MfcUi::TestRunner runner;
根据框中所显示的内容就是错误的位置,直接双击该条,也可以定位到相应代码。该方法必须在MFC下使用。
在目前以VC最为主要开发工具的情况下,使用输出到VC的输出窗口的方法比较合适。
在具体使用后,再提供更具体的使用实例和一些使用方法和技巧。