CppUnitLite源码分析

这几天集中精力阅读2个C++的测试框架源代码,一个是CppUnit,另一个就是今天要说的CppUnitLite啦。

CppUnitLite是一个由Michael Feathers开发的短小精悍的C++测试框架,Michael Feathers同时也是CppUnit的原作者。使用者可以通过这个框架根据自己的实际需要进行扩展。

  1. http://www.objectmentor.com/resources/downloads.html
  2. http://www.objectmentor.com/resources/bin/CppUnitLite.zip

这个框架的目的在于:

  1. 为开发者提供容易编写的独立的测试。
  2. 遵循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

你可能感兴趣的:(框架,windows,测试,单元测试,Symbian,construction)