cppunit与组合模式

     首先看一下类的继承结构吧(斜体代表抽象类):
cppunit与组合模式 - 绚丽也尘埃 - 处女地
      最后存在于内存中的TestSuite和TestCaller对象都是从Test派生而来,TestSuite有这样一个属性:
private:
  CppUnitVector<Test *> m_tests;
      作为component,它可以有很多leaf节点,但是由于它也是从Test派生而来,所以它又可以成为别的component的页节点。
      cppunit运行时,会将一个TestSuite的所有子节点都运行完,不管其是component还是leaf。它能这样做关键在于它的run函数,TestSuite并没有实现自己的run函数,它从TestComponent继承run函数,TestComponent的run函数实现如下:
void
TestComposite::run( TestResult *result )
{
  doStartSuite( result );
  doRunChildTests( result );
  doEndSuite( result );
}
        关键在于第二句,doRunChildTests函数实现如下:
void
TestComposite::doRunChildTests( TestResult *controller )
{
  int childCount = getChildTestCount();
  for ( int index =0; index < childCount; ++index )
  {
    if ( controller->shouldStop() )
      break;

    getChildTestAt( index )->run( controller );
  }
}

注意最后一句,如果getChildTestAt( index )得到的是一个TestSuite对象,那么它又会调用上面的TestComponent::run,这样迭代下去;如果是一个TestCaller对象,那么就会调用TestCaller::run函数,其实现代码如下:
/// Run the test and catch any exceptions that are triggered by it
void
TestCase::run( TestResult *result )
{
  result->startTest(this);

  if ( result->protect( TestCaseMethodFunctor( this, &TestCase::setUp ),
                        this,
                       "setUp() failed" ) )
  {
    result->protect( TestCaseMethodFunctor( this, &TestCase::runTest ),
                     this );
  }

  result->protect( TestCaseMethodFunctor( this, &TestCase::tearDown ),
                   this,
                   "tearDown() failed" );

  result->endTest( this );
}

      由此可以看出TestSuite和TestCaller的run函数的各自实现是很关键的,这样可以保证整棵树完整被运行。顺便提一下,TestComposite这个类只有一个“std::string m_name”属性,但是它却能实现run函数,如果让我自己来设计的话,我可能会将这个run函数的详细实现放到TestSuite对象中,因为TestSuite才有保存Test的容器。但是TestComposite实现这个函数有其合理性。
      另外还有一处用到了工厂模式。TestFactoryRegistry从TestFactory派生,同时其有一个属性:
  typedef CppUnitSet<TestFactory *, std::less<TestFactory*> > Factories;
  Factories m_factories;
       所以工厂也可以组成一棵树,大工厂包含小工厂,小工厂再包含小工厂。工厂的makeTest方法返回的是TestSuite对象,所有一个树形的工厂生产出来的TestSuite对象也会维持其相应的树状。cppunit也提供了这样一个宏来简化我们的操作,该宏定义如下:
#define CPPUNIT_REGISTRY_ADD( which, to )                                     \
  static CPPUNIT_NS::AutoRegisterRegistry                                     \
             CPPUNIT_MAKE_UNIQUE_NAME( autoRegisterRegistry__ )( which, to )
当然我们也可以自己手工来操作。比如这样:
CPPUNIT_NS::TestFactoryRegistry::getRegistry("My Test").addRegistry("All Tests");
这样就有意思地将"All Tests"变成了"My Test"工厂的子工厂。
       最后用到组合的模式的地方是protectchain,这个类从protector派生,其内部又有一个deque容器保存protector指针,这样就可以极大地扩展protectchain。不过cppunit中起作用也就是一个default protector,并没有复杂的应用。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值