这几天集中精力阅读2个C++的测试框架源代码,一个是CppUnit,另一个就是今天要说的CppUnitLite啦。
CppUnitLite是一个由Michael Feathers开发的短小精悍的C++测试框架,Michael Feathers同时也是CppUnit的原作者。使用者可以通过这个框架根据自己的实际需要进行扩展。
- http://www.objectmentor.com/resources/downloads.html
- http://www.objectmentor.com/resources/bin/CppUnitLite.zip
这个框架的目的在于:
- 为开发者提供容易编写的独立的测试。
- 遵循JavaUnit的模式,避免使用C++的一些高级特性,比如RTTI,异常,模板等,这些因素不利于程序的移植。
现在假设有一个Deque类需要测试,测试所用的代码如下:
#include "TestHarness.h"
#include "Deque.h"
//from http://www.cnblogs.com/gpcuster
int main ()
{
TestResult tr ;
TestRegistry :: runAllTests ( tr );
return 0 ;
}
TEST ( Deque , construction )
{
Deque d ;
CHECK ( 0 == d . size () );
}
TEST ( Deque , dont_try_suicide )
{
Deque d ;
d . push_front ( 1 );
d = d ;
CHECK ( 1 == d . pop_front ());
}
tr是用来保存测试的结果的,你可以通过继承TestResult 来添加自己需要,比如显示成功的测试有多少,失败的测试有多少。
TestRegistry :: runAllTests ( tr ); 这段代码表示开始执行测试。朋友们一定就会问啦,需要测试的代码是怎么关联进去的?要回答这个问题,我们可以看看实际要测试的代码,比如
TEST ( Deque , construction )
{
Deque d ;
CHECK ( 0 == d . size () );
}
这个函数看起来很奇怪,其实TEST是一个宏定义,这个框架中定义啦一个Test的基类,作者使用啦一个非常巧妙的宏(TEST)来生成一个派生与Test的类型,类型的名称由这个看似函数而不是函数的第一个参数(Deque)和第二个参数(construction)组成。同时实现啦Test::run函数,这里的实现也就是
{
Deque d ;
CHECK ( 0 == d . size () );
}
其中的CHECK ( 0 == d . size () ); 也是用宏实现的。
为了能让大家看得更清楚,我们看看
TEST ( Deque , construction )
{
Deque d ;
CHECK ( 0 == d . size () );
}
这段代码在编译的时候变成了这个样子:
class constructionDequeTest : public Test
{
public :
constructionDequeTest () : Test ( "Deque" "Test" ) {} /
void run ( TestResult & result_ );
} constructionDequeInstance ;
void constructionDequeTest :: run ( TestResult & result_ )
{
Deque d ;
//CHECK ( 0 == d.size() );
{
if (!( 0 == d . size ()))
{
result_ . addFailure ( Failure ( name_ , __FILE__ , __LINE__ , "0 == d.size()" ));
return ;
}
}
}
这样,在编译的时候就自动生成啦一个用于测试类。
注意类定义的最后同时进行了实例化constructionDequeInstance ,通过查看Test的代码你会发现,在实例话的时候调用了TestRegistry :: addTest ( this ); 这样,就把这个测试类的代码添加到了TestRegistry 中去,同时TestRegistry 又实现啦Singleton Pattern 单件模式,所以我们也就很自然地回答了开始的问题(TestRegistry :: runAllTests ( tr ); 这段代码表示开始执行测试。朋友们一定就会问啦,需要测试的代码是怎么关联进去的?)。
如果大家有兴趣,可以进一步看一看Google公布的开源c++单元测试框架googletest
Google's framework for writing C++ tests on a variety of platforms (Linux, Mac OS X, Windows, Cygwin, Windows CE, and Symbian). Based on the xUnit architecture. Supports automatic test discovery, a rich set of assertions, user-defined assertions, death tests, fatal and non-fatal failures, value- and type-parameterized tests, various options for running the tests