//helloworld.cpp
#include <iostream>
#include <cppunit/TestRunner.h>
#include <cppunit/TestResult.h>
#include <cppunit/TestResultCollector.h>
#include <cppunit/extensions/HelperMacros.h>
#include <cppunit/BriefTestProgressListener.h>
#include <cppunit/extensions/TestFactoryRegistry.h>
//创建一个测试用例,继承自TestCase
//该测试用例里面有一个测试函数
class Test : public CPPUNIT_NS::TestCase
{
//这三个宏是固定的写法,第一行Test是当前类的名字
//该类里面有多少测试方法,就在中间加上多少行,每一行的参数都是一个函数名
//最后一行是不变的
CPPUNIT_TEST_SUITE(Test); //宏内调用了setUp函数
CPPUNIT_TEST(testHelloWorld);//每一个函数的测试方法注册到该测试用例中
//CPPUNIT_TEST(testMath);
CPPUNIT_TEST_SUITE_END();//宏内调用了tearDown函数
public:
void setUp(void) {}
void tearDown(void) {}
protected:
void testHelloWorld(void) { std::cout << "Hello, world!" << std::endl; }
/*
void testMath(void)
{
//VOID
}
*/
};
//该宏自动将上面定义的测试用例,注册到一个用例库中,通过CPPUNIT_NS::TestFactoryRegistry::getRegistry().makeTest()就可以得到其包含的所有测试用例
CPPUNIT_TEST_SUITE_REGISTRATION(Test);
int main( int argc, char **argv )
{
// 创建一个测试控制器
CPPUNIT_NS::TestResult controller;
// 创建一个测试结果控制器
CPPUNIT_NS::TestResultCollector result;
//添加到controller中
controller.addListener( &result );
// 往controller中添加一个运行中用打点的方式来显示进度的功能
CPPUNIT_NS::BriefTestProgressListener progress;
controller.addListener( &progress );
// 创建测试用例运行者
CPPUNIT_NS::TestRunner runner;
//从注册库中取测试用例,增加到runer中,准备逐一运行
runner.addTest( CPPUNIT_NS::TestFactoryRegistry::getRegistry().makeTest() );
runner.run( controller );
//如果所以测试用例都run成功,则测试成功!
return result.wasSuccessful() ? 0 : 1;
}
这个代码的最终输出是打印到屏幕的Hello World!但是,它在后面进行了很多工作,继承TestCase生成了一个自己的测试用例,将其注册到用例库中,对测试的运行环境进行了设置,然调用TestRunner运行测试用例,最终得到测试的成功与否!
通过上面的例子,还可以知道如下几点:
1. CPPUNIT内部使用了很多的宏定义,这些宏分别分布在cppunit的众多头文件里面,所以在使用CPPUNIT时,要引入很多的头文件;
2. CPPUNIT的语法风格非常的面向应用,语义性很强。例如“测试用例”,“测试运行着”,“运行结果”等类;
3. 通过宏的使用,main函数中跟具体测试类相关的代码已经完全不存在了,下次在增加新的测试用例,无需对main函数进行任何修改。可见,CPPUNIT的自动化程度是很高的,同时测试框架的可复用性很高,无形降低了初学者的使用成本。