我看CPPUNIT的测试类

虽然help文档写的很好,但是我感觉还是CPPUNIT的框架比较难以掌握。其中一个原因当然是因为我的C++基础比较差,看C++代码比较吃力,而且也不懂设计模式,所以不知道那一大堆的抽象类,工厂类为啥要继承来继承去。幸好网上有许多大侠写的入门文档和源码解读(如morning大侠的文档,THX,morning大师),

把我自己混乱的思路整理如下:

首先要明白CPPUNIT里面所有的测试是按树状组织的,这很重要。

 

然后可以具体看每个类的作用:

 

Test:

Test类是所有具有测试特性的类型的基类,它只定义了测试的名字,运行方法(run),对子节点数统计这些公共特性。

TestFixture:

TestFixture类是所有具有建立环境,和撤销环境类的的基类,它只定义了setUptearDown这两个公共方法

TestCase

不难想见,如果一个测试需要建立环境,和撤销环境的操作,那么它既是一个Test,也是一个TestFixture,它应该是二者的子类,所以TestCase就是一个这样的类型,它重载了run方法,并定义另外一个runTest的的具体方法,二者的区别是run方法中包括了一些异常处理和测试开始,结束时的一些操作,这里被剔除掉了,保留了一个干净的runTest函数,也就是我们想要运行的测试内容。

TestSuite:

测试往往是相联系的,比如说要测试扫频,那么测试内容就包括向物理层配置数据是否正确,回读数据是否合法等一系列相关测试,我们希望能够把这些测试组合在一起。TestSuite包括指向一系列Test对象的指针vecotr,可以表达这个关系,但是TestSuite本身也是一个Test,据说这就是Composite Pattern的设计方法,不懂L,它重载run方法,也就是对每个指向的Test对象依次调用它们的run方法。并自然地,有添加,删除这些Test对象的方法。

这样看起来好像很简单,事实上实际做法要复杂些,比如TestSuiteTest之间隔了一个TestComposite类,TestCaseTest之间隔了一个TestLeaf类,也就是说,伊们都是TestSuite的孙女而不是女儿。隔一层可能是为了接口漂亮或是未来的扩展性,因为我看到TestSuiteTestCase都是独女,因此是为了搞出漂亮的树结构的可能性较大。

TestCaller

TestCase的女儿,将要测试的方法又包了一层,和一个TestFixture的实例绑定,一个TestSuite可以包含若干个TestCaller,因为TestCallerTest的曾孙女。每个TestCaller运行都会重新掉一遍setUptearDown

NamedRegistries

前面说过这个所有的测试是按树状组织的,那么可能有很多棵树,每棵树都要有自己的根节点和名称,为了方便查找和管理,必然有个数据结构来维护管理,NamedRegistires就是干这个的,事实上,下面会看到,它维护的不像刚才说的是树的实体那么简单,实现要复杂得多。这个类维护一个全局唯一的实例,内部维护的其实是一个字符串和TestFactoryRegistry对应的map。

TestFactory

Test的抽象工厂类,仅仅包含一个makeTest的纯虚函数,该函数可以返回一个Test的实例。

TestFactoryRegistry

TestFactory的子类和注册类,什么是注册类?我也不是很懂,但是冒着牛人的无情鄙视,可以把它把它简单理解为C里面的指针数组,也就是说通过一个TestFactoryRegistry可以访问到一坨TestFactory,就像int *p[10]和int的关系一样。而NamedRegistires里面,其实维护的是一组TestFactoryRegistry,所以我们可以继续无耻地把NamedRegistires理解为指向指针数组的指针数组。TestFactory实现了makeTest函数,就是新产生一个空的suite,当它调用addTestToSuite增加一个test到这个suite的时候,会导致它所"指向"的所有TestFacory类都调用makeTest,并一一添加到这个suite里面,形成一个递归调用,构成所有的suite。

TestSuiteFactory

模板类,TestFactory的女儿,是TestFixture的类工厂,该TestFixture必须有一个静态的suite方法来在其覆盖makeTest这个函数时调用。它负责建立有具体内容的suite。

 

不知有没有人有耐心看到这里面,现在总的机制应该比较清楚了:

  1. 首先我们写一个自己的类,比如MyTestFixture继承TestFixture,这个函数要有自己的setUptearDownsuite方法,并且带若干个测试函数。setUptearDown里是建立和退出代码,测试函数里写你的测试代码。
  2. 在suite方法里,我们先建立一个空的TestSuite实例,产生若干个MyTestFixture的实例,再把自己的测试函数和对应的实例封装为TestCaller对象,加入这个TestSuite
  3. 有了MyTestFixture,我们可以根据这个MyTestFixture生成其对应的(TestSuiteFactory)工厂类MyTestSuiteFactoryMyTestSuiteFactory由于是一个TestFactory,因此可以被加入到一个TestFactoryRegistry中管理,将MyTestSuiteFactory加入到你想要加入的那个TestFactoryRegistry
  4. 新的TestFixture类,重复以上步骤,构成树状,此时树为工厂方法的树。
  5. 全部准备好后,调用树的根节点(TestFactoryRegistry)的makeTest方法,引发递归调用,生成真正的Test树

 

应该就是这样,不过CPPUNIT提高了一系列宏来简化以上步骤。

 

PS:

虽然这个东东让我懂得了虚类除了做接口外还可以代表性质等,但作为一个多年学C++未遂的人来说,我忍不住要抱怨:OO虽然有许多优点,但是易于学习绝不是其中之一,事实证明要学会OO要比面向过程难很多,所以教科书上不要再说这种东西符合人类的思维方式了。同时C++这种东西过于强大,强大到像核武器一样必须用设计模式和多条设计规则约束。所以对我们这些只懂得一点点语法入门级的菜鸟来说看的仿佛就是天书,就好像听得明白do,rui,mi,fa,so,但是谱成交响乐,就基本上不知道要表达啥意思,纯受鄙视。

你可能感兴趣的:(设计模式,数据结构,框架,测试,OO,文档)