分享
 
 
 

CppUnit源码解读(3)

王朝other·作者佚名  2006-01-09
窄屏简体版  字體: |||超大  

【声明】如需复制、传播,请附上本声明,谢谢。原文出处:http://morningspace.51.net/moyingzz@etang.com

测试结果记录相关

从这里开始,将要讲述core中,测试结果记录的相关部分。

CppUnit是支持多线程的,你可以在一个线程中执行测试,在另一个线程中收集测试结果;或者在不同线程中并行执行多个测试,而用一个线程收集测试结果。framework中为此提供了简单而必要的支持。

[SynchronizedObject] 相关文件:SynchronizedObject.h,SynchronizedObject.cpp SynchronizedObject用来管理一个被同步对象,前面提到的TestResult就是从该类派生的。所谓被同步对象,是指其成员会被多个线程并发使用。 SynchronizedObject定义了一个public属性的abstract inner class——SynchronizationObject,代表具备同步属性的对象: class SynchronizationObject{ public: SynchronizationObject() {} virtual ~SynchronizationObject() {} virtual void lock() {} virtual void unlock() {}};此类定义了互斥锁功能,但具体行为需在其派生类中实现。不同环境下的实现方式想必也不尽相同。随CppUnit源码所附的范例中有个MfcSynchronizationObject就是SynchronizationObject的子类,它使用了MFC的CCriticalSection: class MfcSynchronizationObject : public CppUnit::SynchronizedObject::SynchronizationObject{ CCriticalSection m_syncObject;public: void lock() { m_syncObject.Lock(); } void unlock() { m_syncObject.Unlock(); }};SynchronizedObject还定义了一个protected属性的inner class——ExclusiveZone,作为内部使用的辅助类。它用于在当前作用域内锁定一个SynchronizationObject的实例。其实现类似于std::auto_ptr,它持有一个指向SynchronizationObject对象的指针,ctor中调用lock,dtor中调用unlock: class ExclusiveZone{ SynchronizationObject *m_syncObject; public: ExclusiveZone( SynchronizationObject *syncObject ) : m_syncObject( syncObject ) { m_syncObject->lock(); } ~ExclusiveZone() { m_syncObject->unlock (); }};除去这些,SynchronizedObject就很简单了。它持有一个指向SynchronizationObject实例的指针: SynchronizationObject *m_syncObject;并管理其生命周期,在dtor中delete之。至于如何传入该指针,则提供了两种方法: SynchronizedObject::SynchronizedObject( SynchronizationObject *syncObject ) : m_syncObject( syncObject == 0 ? new SynchronizationObject() : syncObject ){}void SynchronizedObject::setSynchronizationObject( SynchronizationObject *syncObject ){ delete m_syncObject; m_syncObject = syncObject;}在讲述TestResult之前,还有一些障碍要扫清。 [TestListener] 相关文件:TestListener.h CppUnit的测试结果记录使用了Observer Pattern,在GoF中对该pattern有如下描述:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。在测试执行的过程中,当发生错误时,TestResult就会被告知,而后它会将该信息传递给TestListener。因此,TestResult对应了Observer Pattern中的Subject,而TestListener则对应了Observer。 不过TestListener只是一个什么事都没做的基类,像输出测试结果这样事情还得留待派生类来解决,比如outputter部分要提到的TextTestProgressListener。此外,还是尽量不要使用Listener进行测试结果的输出为好,应该使用outputter中所提供的专有工具。 从TestListener的定义可以看到,在如下三类事件发生时,TestListener将会被通知到 测试执行之前 测试失败 测试执行之后 来看一下代码: // 在一个测试运行前被调用virtual void startTest( Test *test ) {}// 运行测试失败时被调用virtual void addFailure( const TestFailure &failure )// 在一个测试运行后被调用virtual void endTest( Test *test )addFailure中的failure是临时对象,在该方法调用之后即被销毁,和Exception一样(参见TestCase的run函数),也需要使用其自身提供的clone方法来创建一个副本。有关TestFailure,稍后将会提到。 至于endTest,即便测试失败,该函数也会被调用,参见TestCase的run函数。 [TestResult] 相关文件:TestResult.h,TestResult.cpp 真是千呼万唤始出来啊。TestResult用以收集测试过程中的相关信息,它派生自SynchronizedObject,从而支持多线程。有了前面的铺垫,对TestResult的理解就变得非常容易了。 TestResult维护了一个指向TestListener对象的指针队列: protected: typedef std::deque<TestListener *> TestListeners; TestListeners m_listeners;为获取到测试相关信息,TestListener需要注册到TestResult中,于是就有了addListener方法: void TestResult::addListener( TestListener *listener ){ ExclusiveZone zone( m_syncObject ); // ExclusiveZone终于有用武之地了 m_listeners.push_back( listener );}当然还少不了removeListener: void TestResult::removeListener ( TestListener *listener ){ ExclusiveZone zone( m_syncObject ); m_listeners.erase( std::remove( m_listeners.begin(), m_listeners.end(), listener ), m_listeners.end());}我们再来看看TestResult作为Subject的那些Notify方法: void TestResult::addError( Test *test, Exception *e ){ addFailure( TestFailure( test, e, true ) );}void TestResult::addFailure( Test *test, Exception *e ){ addFailure( TestFailure( test, e, false ) );}void TestResult::addFailure( const TestFailure &failure ){ ExclusiveZone zone( m_syncObject ); // 遍历deque<TestListener *> for ( TestListeners::iterator it = m_listeners.begin(); it != m_listeners.end(); ++it ) (*it)->addFailure( failure ); // 调用TestListener的addFailure}void TestResult::startTest( Test *test ){ ExclusiveZone zone( m_syncObject ); // 遍历deque<TestListener *> for ( TestListeners::iterator it = m_listeners.begin(); it != m_listeners.end(); ++it ) (*it)->startTest( test ); // 调用TestListener的startTest}void TestResult::endTest( Test *test ){ ExclusiveZone zone( m_syncObject ); // 遍历deque<TestListener *> for ( TestListeners::iterator it = m_listeners.begin(); it != m_listeners.end(); ++it ) (*it)->endTest( test ); // 调用TestListener的endTest}此处的注释足以说明问题,至于error和failure的区别,在讲到TestFailure时自然会明了。 最后再来看看有关shouldStop的代码,该函数曾在TestSuite的run中出现过: TestResult::TestResult( SynchronizationObject *syncObject ) : SynchronizedObject( syncObject ){ reset();}void TestResult::reset(){ ExclusiveZone zone( m_syncObject ); m_stop = false;}bool TestResult::shouldStop() const{ ExclusiveZone zone( m_syncObject ); return m_stop;}void TestResult::stop(){ ExclusiveZone zone( m_syncObject ); m_stop = true;}没有什么特别的,只是一个m_stop在掌控着一切,而m_stop则是TestResult的一个protected属性的成员变量: bool m_stop;

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有