标签 开源 下的文章

CppUnit入门实践-Tony与Alex的对话系列

Tony : Hi Alex ! you just looks like drowing in your project. what is up?
Alex : 我们的项目要求引入单元测试,but i've no experience in unit test.
Tony : i think cppunit is your best choice.
Alex : 是的,我刚从网上把它down了下来,正准备研究它呢。
Tony : Really ? I have done some practice on unit test before. would you like me to join you?
Alex : Oh Tony, I'm so glad that you could help me !
Tony : My pleasue !
Alex : 我们从哪里开始呢?
Tony : The simplest case! 我们拿一个最简单的例子吧。now we have a class with the name "SimpleCalculator" and it has four basic methods 'add', 'sub', 'mul' and 'div', All we should do is to test whether these methods run as same as we expect. First of all , complete the "SimpleCalculator" class, Alex.
Alex : It is simple!

//SimpleCalculator.h
class SimpleCalculator{
 public :
  int add(int a, int b);
  int sub(int a, int b);
  int mul(int a, int b);
  int div(int a, int b);
};

//SimpleCalculator.cpp
int SimpleCalculator::add(int a, int b){
 return a+b;
}

int SimpleCalculator::sub(int a, int b){
 return a-b;
}

int SimpleCalculator::mul(int a, int b){
 return a*b;
}

int SimpleCalculator::div(int a, int b){
 return a/b;
}

Alex : 这里简单点,div方法没有考虑0作除数的异常情况。
Tony : 可以。还记得我上次讲的测试驱动开发么,不过今天我们不是用它,我们只做些简单的东西,目的就是为了熟悉工具的使用。
Alex : 那我们是不是也应该列出一个test case的list亚?
Tony : 没错。
Alex : 我来随意写几个吧。“add(5,6) == 11” 、“sub(5,6)==-1”、“mul(5,6) == 30”和“div(12,6) == 2”。
Tony : 然后我们一起来学习一下CppUnit的帮助文档吧。

(Tony and Alex are reading the doc of cppunit.)

Tony : 学到了些什么?
Alex : 看来这些xUnit框架的测试工具在概念上几乎是一致的,像TestCase、TestFixture和TestSuite这些概念都大同小异。
Tony : 不错,单元测试在于测试思想,工具只是个必要条件而已,工具并不能决定你的测试就是一个好的测试。下面你就按你理解的CppUnit去做吧。

Alex : Ok. 按照书中所说,我们一次要测试多个method,最好使用TestFixture。我是这样写的,你看看。

#include "SimpleCalculator.h"
#include "CppUnit/TestCase.h"
#include "CppUnit/TestResult.h"
#include "CppUnit/TextOutputter.h"
#include "CppUnit/TestResultCollector.h"
#include "CppUnit/TestCaller.h"
#include "CppUnit/extensions/HelperMacros.h"

class SimpleCalcTest : public CPPUNIT_NS::TestFixture{
private :
 SimpleCalculator * sc;

public:
 virtual void setUp(){
         sc = new SimpleCalculator();
     }
     virtual void tearDown(){
         delete sc;  
     }
 
 void testAdd(){       
         CPPUNIT_ASSERT_EQUAL( sc->add(5,6), 11);
     }

 void testSub(){       
         CPPUNIT_ASSERT_EQUAL( sc->sub(5,6), -1 );
     }

     void testMul(){       
         CPPUNIT_ASSERT_EQUAL( sc->mul(5,6), 30 );
     }

 void testDiv(){       
         CPPUNIT_ASSERT_EQUAL( sc->div(12,6), 2 );
     }
};

我们的主函数如下:
int main()
{
    CPPUNIT_NS::TestResult r;
    CPPUNIT_NS::TestResultCollector result;
    r.addListener( &result );

    CPPUNIT_NS::TestCaller testCase1( "testAdd", &SimpleCalcTest::testAdd );
    CPPUNIT_NS::TestCaller testCase2( "testSub", &SimpleCalcTest::testSub );
    CPPUNIT_NS::TestCaller testCase3( "testMul", &SimpleCalcTest::testMul );
    CPPUNIT_NS::TestCaller testCase4( "testDiv", &SimpleCalcTest::testDiv );
   
    testCase1.run( &r );
    testCase2.run( &r );
    testCase3.run( &r );
    testCase4.run( &r );
   
    CPPUNIT_NS::TextOutputter out( &result, std::cout );
    out.write();
    return 0;
}

Tony : 我觉得可行。运行一下,看看如何。
Alex : 输出结果如下:
OK (4 tests)

Tony : 这的确是一种可行的办法,不过你回想一下我们一起学习的doc中的内容,看看是否还有改进的余地了。现在如果你要在SimpleCalcTest类中加一个测试用例方法,不仅仅SimpleCalcTest要修改,我们的main函数也需要修改,还记得JUnit中有什么概念来支持么?

Alex : 你不提我还真的记不起来了,JUnit中有TestSuite,刚才在cppunit doc中我也看到了suite方法,也许会帮得上忙,稍等一下我再翻翻文档….

Alex : 我找到了。的确有更为简单的方法。我修改一下,引用的头文件不变。

class SimpleCalcTest : public CPPUNIT_NS::TestFixture{

    CPPUNIT_TEST_SUITE( SimpleCalcTest );
        CPPUNIT_TEST( testAdd );
        CPPUNIT_TEST( testSub );
        CPPUNIT_TEST( testMul);
        CPPUNIT_TEST( testDiv );       
    CPPUNIT_TEST_SUITE_END();

private :
 SimpleCalculator * sc;

public:
 virtual void setUp(){
         sc = new SimpleCalculator();
     }
     virtual void tearDown(){
         delete sc;  
     }
 
 void testAdd(){       
         CPPUNIT_ASSERT_EQUAL( sc->add(5,6), 11);
     }

 void testSub(){       
         CPPUNIT_ASSERT_EQUAL( sc->sub(5,6), -1 );
     }

     void testMul(){       
         CPPUNIT_ASSERT_EQUAL( sc->mul(5,6), 30 );
     }

 void testDiv(){       
         CPPUNIT_ASSERT_EQUAL( sc->div(12,6), 2 );
     }
};

CPPUNIT_TEST_SUITE_REGISTRATION( SimpleCalcTest );

主函数修改后如下:
int main()
{
    CPPUNIT_NS::TestResult r;
    CPPUNIT_NS::TestResultCollector result;
    r.addListener( &result );

    CPPUNIT_NS::TestFactoryRegistry::getRegistry().makeTest()->run( &r );
    CPPUNIT_NS::TextOutputter out( &result, std::cout );
    out.write();
    return 0;
}

CppUnit利用宏来解决Suite的问题。在你的TestCase定义里面写入如下的这段代码:
CPPUNIT_TEST_SUITE( YourTestCase );
        CPPUNIT_TEST( testXX);
   …//
CPPUNIT_TEST_SUITE_END();
这段代码实际上是定义了一个函数suite,这个函数返回了一个包含了所有CPPUNIT_TEST定义的测试用例的一个测试集。CPPUNIT_TEST_SUITE_REGISTRATION通过静态注册把这个测试集注册到全局的测试树中,最后通过CPPUNIT_NS::TestFactoryRegistry::getRegistry().makeTest()生成一个包含所有测试用例的测试并且运行。这样的话,一旦要添加新的测试用例函数,我们只需要修改SimpleCalcTest类即可。

Tony : Well done! Alex你独立解决问题的能力越来越强了。相信做到这你已经心里有底儿了,再往后就是在你的实际项目中摸索CppUnit的使用经验了。

Alex : 呵呵。谢谢夸奖!

看完“程序员”2005-04期一些想法

每次看完《程序员》杂志都会有些新的收获,这次看的是《程序员》2005年第4期,顺便把一些阅读过程中产生的想法记录了下来。

[软件建模,大势所趋]
看完微软、IBM、Borland等公司的最新动态,感觉软件建模是大势所趋,以前虽然也有众多建模工具,但是由工具支持得不好,建模的各个阶段彼此脱节,使用户体验(user experience)很差。随着Microsoft VSTS(Visual Studio Team System)的发布在即、随着Borland的ALM(Application Lifecycle Management )工具及基于Eclipse的产品计划的实施,相信在不久的将来软件建模会有一个很大的改观。

[源代码就是设计]
Artima上出现了“源代码就是设计”的续篇,作者阐明其观点:
a)“the source code is the design” does not mean “don't do design , just code”;
b) the design is a process but not a product;Somethings like UML diagrams or CRC cards are not the real software design.
c)“we need good architectures (top level design), good abstractions (class design), and good implementations (low level design). ” UML diagrams or CRC cards可以帮我们完成top level design和class design,但是这并不意味着设计结束了。我们还需要low level design — that is the source code。
d)“The only way we validate a software design is by building it and testing it. There is no silver bullet, and no "right way" to do design”作者坚持认为“不到写完代码,代码通过测试,设计工作就不算完。

编码可以看作low level design,它是设计工作的延续,不到编码完成测试结束,我们永远不能知道我们的设计是否正确。

[关注开源,参与开源]
相信现在国内外任何一家软件厂商都不能不考虑“开源的影响力”了。从JDO2.0的起死回生,到EJB 3.0采纳了众多开源组织的建议,我们清醒地看到了这一点。同时我们国内的开源又是怎样的呢?不可否认的是中国的开源发展也是迅速的,但是还远远没达到“普及”的程度。我相信现在国内很多软件公司对开源的理解也只停留在“免费使用”这个层面上,用的时候还要“挑三捡四”一番。这和国外的“开源洪流”形成了鲜明的对比。最近传出Borland公司即将发布基于Eclipse的产品,BEA加入开源世界,虽说这背后有其“利益”因素在驱使,但是这也为我们国内厂商指明了一个大方向“关注开源,参与开源”。开源需要激情,国人期待在中国出现大师级的开源领袖,而实现这一目标首先需要你参与到开源世界中去。希望国内的软件厂商能把眼光放的更远一些,而不仅仅是现在的免费“索取”。

[技术与市场]
这是一个很有意思而又值得大家反思的话题,超前技术到底能不能带来市场收益上的“超前”,当年的Apple公司的Macintosh和鼠标的发明给了我们些许的启示“技术和市场不能脱节”,值得我们反思。

[文档的作用]
文档多被作为一种“成果物”,而不是沟通和交流的手段。大多数人为了文档而文档。文档形成后,便少有人问津了。

[AOP是最佳解决方案]
在最近的通用框架项目中设计“网管”模块,几乎框架中的所有模块都要使用其中的告警机制,感觉如果用AOP实现肯定会特别舒服,不过我们使用的是C语言开发,虽说C语言是“万能的”,不过到现在为止,我还没见到用C实现的AOP框架。

[要事第一]
这几天很多事情都摆在面前,干这件事的时候还在想着另外一件事,导致哪件事都没能做好。突然想起“高效能人士的7个习惯”一书中的一个习惯就是“要事第一”,把自己的事情按优先级分类,确定deadline,这回做起来就顺手一些了。

[习惯的定义]
昨晚,刚刚接受过“高效能人士的7各习惯”培训的my roommate问我一个问题,“什么是习惯”?愕然间,听到他的解析“习惯是知识、技巧与意愿三者的混合体,我们有付诸行动的愿望,在这样的一个思维惯性的推动下,久而久之就形成了经常性的行为–习惯”。Note:习惯是各中性词,怀习惯同样符合这一定义。

[身体才是革命的本钱]
昨天下午突然感觉身体有恙,浑身冒冷汗,做什么都做不进去,离开座位walk around for several minutes,还是感觉极差,所以请了假,早早回了寝室,躺在床上突然想到一句长辈们总在我们耳畔重复的话“身体是革命的本钱”。在寝室看完了上个星期买的《程序员》2005年第4期,写下了以上的文字。

如发现本站页面被黑,比如:挂载广告、挖矿等恶意代码,请朋友们及时联系我。十分感谢! Go语言第一课 Go语言进阶课 Go语言精进之路1 Go语言精进之路2 Go语言第一课 Go语言编程指南
商务合作请联系bigwhite.cn AT aliyun.com

欢迎使用邮件订阅我的博客

输入邮箱订阅本站,只要有新文章发布,就会第一时间发送邮件通知你哦!

这里是 Tony Bai的个人Blog,欢迎访问、订阅和留言! 订阅Feed请点击上面图片

如果您觉得这里的文章对您有帮助,请扫描上方二维码进行捐赠 ,加油后的Tony Bai将会为您呈现更多精彩的文章,谢谢!

如果您希望通过微信捐赠,请用微信客户端扫描下方赞赏码:

如果您希望通过比特币或以太币捐赠,可以扫描下方二维码:

比特币:

以太币:

如果您喜欢通过微信浏览本站内容,可以扫描下方二维码,订阅本站官方微信订阅号“iamtonybai”;点击二维码,可直达本人官方微博主页^_^:
本站Powered by Digital Ocean VPS。
选择Digital Ocean VPS主机,即可获得10美元现金充值,可 免费使用两个月哟! 著名主机提供商Linode 10$优惠码:linode10,在 这里注册即可免费获 得。阿里云推荐码: 1WFZ0V立享9折!


View Tony Bai's profile on LinkedIn
DigitalOcean Referral Badge

文章

评论

  • 正在加载...

分类

标签

归档



View My Stats