【转】CppUnit使用简介
以下内容来自:http://www.cnblogs.com/wishma/archive/2008/08/01/1258370.html
1. 简介
CppUnit 是个基于 LGPL 的开源项目,最初版本移植自 JUnit,是一个非常优秀的开源测试框架。CppUnit 和 JUnit 一样主要思想来源于极限编程(XProgramming)。主要功能就是对单元测试进行管理,并可进行自动化测试。这样描述可能没有让您体会到测试框架的 强大威力,那您在开发过程中遇到下列问题吗?如果答案是肯定的,就应该学习使用这种技术:
- 测试代码没有很好地维护而废弃,再次需要测试时还需要重写;
- 投入太多的精力,找 bug,而新的代码仍然会出现类似 bug;
- 写完代码,心里没底,是否有大量 bug 等待自己;
- 新修改的代码不知道是否影响其他部分代码;
- 由于牵扯太多,导致不敢进行修改代码;
2. 基本思想
对于上面的问题仅仅说明 CppUnit 的使用是没有效果的,下面先从测试的目的,测试原则等方面简要说明,然后介绍 CppUnit 的具体使用。
首先要明确我们写测试代码的目的,就是验证代码的正确性或者调试 bug。这样写测试代码时就有了针对性,对那些容易出错的,易变的编写测试代码;而不用对每个细节,每个功能编写测试代码,当然除非有过量精力或者可靠性要求。
编 码和测试的关系是密不可分的,推荐的开发过程并不要等编写完所有或者很多的代码后再进行测试,而是在完成一部分代码,比如一个函数, 之后立刻编写测试代码进行验证。然后再写一些代码,再写测试。每次测试对所有以前的测试都进行一遍。这样做的优点就是,写完代码,也基本测试完一遍,心里 对代码有信心。而且在写新代码时不断地测试老代码,对其他部分代码的影响能够迅速发现、定位。不断编码测试的过程也就是对测试代码维护的过程,以便测试代 码一直是有效的。有了各个部分测试代码的保证,有了自动测试的机制,更改以前的代码没有什么顾虑了。在极限编程(一种软件开发思想)中,甚至强调先写测试 代码,然后编写符合测试代码的代码,进而完成整个软件。
根据上面说的目的、思想,下面总结一下平时开发过程中单元测试的原则:
- 先写测试代码,然后编写符合测试的代码。至少做到完成部分代码后,完成对应的测试代码;
- 测试代码不需要覆盖所有的细节,但应该对所有主要的功能和可能出错的地方有相应的测试用例;
- 发现 bug,首先编写对应的测试用例,然后进行调试;
- 不断总结出现 bug 的原因,对其他代码编写相应测试用例;
- 每次编写完成代码,运行所有以前的测试用例,验证对以前代码影响,把这种影响尽早消除;
- 不断维护测试代码,保证代码变动后通过所有测试;
有上面的理论做指导,测试行为就可以有规可循。那么 CppUnit 如何实现这种测试框架,帮助我们管理测试代码,完成自动测试的?下面就看看 CppUnit 的原理。
3. cppunit的基本原理
CppUint进行测试的基本原理是:对于每一批测试,编写一个继承自TestFixture的测试类,其中setUp和tearDown 两个虚函数分别用于进行测试数据的初始化和释放操作;对于每一项测试,分别定义一个void返回类型的无参数方法,检测测试过程,可以用以下几个宏:
CPPUNIT_ASSERT(condition) |
断言condition为真,否则失败 |
CPPUNIT_ASSERT_MESSAGE(message,condition) |
当condition为假时失败, 并打印message |
CPPUNIT_FAIL(message) |
当前测试失败, 并打印message |
CPPUNIT_ASSERT_EQUAL(expected, actual) |
确信两者相等,否则失败 |
CPPUNIT_ASSERT_EQUAL_MESSAGE(message, expected, actual) |
确信两者相等,否则失败,并同时打印message |
CPPUNIT_ASSERT_DOUBLES_EQUAL(expected, actual, delta) |
当expected和actual之间差大于delta时失败 |
其中,“失败”的含义就是程序运行出现异常,并且所有测试过程中止。
在完成一个或者多个测试类的编写后,需要用TestRunner类的实例来运行每个测试类的测试函数进行测试。TestRunner类型共有:TextUi::TestRunner,QtUi::TestRunner,MfcUi::TestRunner三个,都可以用来运行测试,其区别为:
TextUi::TestRunner |
默认将信息输出到控制台,也可以指定输出到std::ostringstream。 |
QtUi::TestRunner |
用QT的GUI输出信息 |
MfcUi::TestRunner |
用MFC的GUI输出信息 |
整个测试过程需要另外附加代码,所以通常情况下,测试用例代码和被测试对象因在不同的项目中。应该在另一个项目(最好在不同的目录)中编写测试类,然后把被测试的对象包含在测试项目中。根据测试工程建立的类型,Consol可以选择TextUi::TestRunner,将结果输出至控制台显示,MFC的GUI可以使用MfcUi::TestRunner,使用GUI来控制并查看测试结果。测试工程与被测试对象所在工程的类型是可以不同的。
在使用VC作为开发工工具时,建议使用TextUi::TestRunner,并更改其Outputter实例,使用附加的TraceOutputter,将信息输出到信息输出栏,双击信息输出栏中一行,即可定位到出错位置。
4. 建立cppunit测试实例的一般步骤
建立一个cppunit测试实例的一般步骤如下:
- 包含文件#include <cppunit/extensions/HelperMacros.h>
- 声明一个类,比如,MathTest,继承自CppUnit::TestFixture。
- 声明setUp和tearDown函数。
- 声明测试函数,比如testAdd
- 如果含有其他测试函数,继续添加。
- 在类声明部分添加如下宏,声明改类为测试类,并且声明那些函数为测试函数
CPPUNIT_TEST_SUITE( MathTest); //声明一个TestSuite CPPUNIT_TEST( testAdd ); //添加TestCase到TestSuite /* 定义的TestCase需要在此声明。如果有其他TestCase,可以继续添加到此处 */ CPPUNIT_TEST_SUITE_END(); //TestSuite声明完成
7. 最后在实现的CPP文件中,添加下面的宏,用于注册测试类到某个测试项目,比如以"alltest"命名的项目。
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( MathTest, "alltest" );
8. 实现setUp和tearDown,以及各个测试函数。
6. cppunit的测试代码实例
需要测试的类名为Math,待测试的函数的Math::testAdd().
//Math.h class Math{ public: Math(); ~Math(); int add(int, int); }; //Math.cc #include "Math.h" int Math::add(int x, int y){ return x+y; }
cppunit测试代码如下:
//MathTest.h #include "cppunit/TestFixture.h" #include "cppunit/extensions/HelperMacros.h" class MathTest:public CppUnit::TestFixture{ CPPUNIT_TEST_SUITE(MathTest); CPPUNIT_TEST(testAdd); CPPUNIT_TEST_SUITE_END(); protected: int m_value1, m_value2; public: MathTest(){} void setUp(); void tearDown(); void testAdd(); }; //MathTest.cc #include "MathTest.h" #include "Math.h" #include "cppunit/TestAssert.h" CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(MathTest, "alltest"); void MathTest::setUp(){ m_value1 = ; m_value2 = ; } void MathTest::tearDown(){ } void MathTest::testAdd(){ int ret = m_value1 + m_value2; CPPUNIT_ASSERT(ret == ); }
测试的主代码如下:
#include "Math.h" #include "MathTest.h" #include <iostream> #include "cppunit/ui/text/TestRunner.h" #include "cppunit/extensions/TestFactoryRegistry.h" int main(void){ CppUnit::TextUi::TestRunner runner; CppUnit::TestFactoryRegistry ®istry = CppUnit::TestFactoryRegistry::getRegistry("alltest"); runner.addTest(registry.makeTest()); runner.run(); }
编译: g++ Math.cpp MathTest.cpp main.cpp -lcppunit -ldl -lm -lpthread -o mathTest
运行: ./mathTest
显示:
通过的情况:OK (1 tests)
失败的情况:会显示那个测试类中的哪行测试不通过
!!!FAILURES!!! Test Results: Run: 1 Failures: 1 Errors: 0 1) test: MathTest::testAdd (F) line: 15 MathTest.cpp assertion failed - Expression: ret==4
【转】CppUnit使用简介的更多相关文章
- Assignment3:白盒测试以及测试框架简介
一. 白盒测试简介 白盒测试又称结构测试.透明盒测试.逻辑驱动测试或基于代码的测试.白盒测试是一种测试用例设计方法,盒子指的是被测试的软件,白盒指的是盒子是可视的,你清楚盒子内部的东西以及 ...
- ASP.NET Core 1.1 简介
ASP.NET Core 1.1 于2016年11月16日发布.这个版本包括许多伟大的新功能以及许多错误修复和一般的增强.这个版本包含了多个新的中间件组件.针对Windows的WebListener服 ...
- MVVM模式和在WPF中的实现(一)MVVM模式简介
MVVM模式解析和在WPF中的实现(一) MVVM模式简介 系列目录: MVVM模式解析和在WPF中的实现(一)MVVM模式简介 MVVM模式解析和在WPF中的实现(二)数据绑定 MVVM模式解析和在 ...
- Cassandra简介
在前面的一篇文章<图形数据库Neo4J简介>中,我们介绍了一种非常流行的图形数据库Neo4J的使用方法.而在本文中,我们将对另外一种类型的NoSQL数据库——Cassandra进行简单地介 ...
- REST简介
一说到REST,我想大家的第一反应就是“啊,就是那种前后台通信方式.”但是在要求详细讲述它所提出的各个约束,以及如何开始搭建REST服务时,却很少有人能够清晰地说出它到底是什么,需要遵守什么样的准则. ...
- Microservice架构模式简介
在2014年,Sam Newman,Martin Fowler在ThoughtWorks的一位同事,出版了一本新书<Building Microservices>.该书描述了如何按照Mic ...
- const,static,extern 简介
const,static,extern 简介 一.const与宏的区别: const简介:之前常用的字符串常量,一般是抽成宏,但是苹果不推荐我们抽成宏,推荐我们使用const常量. 执行时刻:宏是预编 ...
- HTTPS简介
一.简单总结 1.HTTPS概念总结 HTTPS 就是对HTTP进行了TLS或SSL加密. 应用层的HTTP协议通过传输层的TCP协议来传输,HTTPS 在 HTTP和 TCP中间加了一层TLS/SS ...
- 【Machine Learning】机器学习及其基础概念简介
机器学习及其基础概念简介 作者:白宁超 2016年12月23日21:24:51 摘要:随着机器学习和深度学习的热潮,各种图书层出不穷.然而多数是基础理论知识介绍,缺乏实现的深入理解.本系列文章是作者结 ...
随机推荐
- Android开发之点击两次Back键退出App
Back按键的方法是onKeyDown()方法,重写该方法就可以改变back按键的作用. 实现点击两次Back按键退出app,有两种方法: 方法1. private static boolean is ...
- sdut 2482 二叉排序树
题目:http://acm.sdut.edu.cn/sdutoj/problem.php?action=showproblem&problemid=2482 感觉树这一部分掌握的真心不好,以前 ...
- mysql 查看表的类型
MySQL 数据表主要支持六种类型 ,分别是:BDB.HEAP.ISAM.MERGE.MYISAM.InnoBDB. 这六种又分为两类,一类是”事务安全型”(transaction-safe),包括B ...
- 在Silverlight中的DispatcherTimer的Tick中使用基于事件的异步请求
需求:在silverlight用户界面上使用计时器定时刷新数据. 在 Silverlight 中的 DispatcherTimer 的 Tick 事件 中使用异步请求数据时,会出现多次请求的问题,以下 ...
- 「拒絕存取路徑 'C:\Users\xxx\AppData\Local\Temp\Temporary ASP.NET Files\apname\3a1b3704\f7fc6d0c\App_Code.l8ieogii.0.cs」的錯誤!
修改web.config中的system.web->compilation tag中,多加入tempDirectory="可存取的目錄" <system.web&g ...
- FJOI2007轮状病毒
不会推公式…… 不会基尔霍夫矩阵…… 不会matrix—tree定理…… 膜拜vfleaking大神…… 题解:http://z55250825.blog.163.com/blog/static/15 ...
- DbHelper and OracleHelper
1 连接Sql Server的ConnectionString: Data Source=.;Initial Catalog=ViewVideo;User ID=sa;Password=XXXXXX; ...
- HDU 4393 Throw nails
Throw nails Time Limit: 5000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total ...
- C# 中的装箱与拆箱
转角撞倒猪 原文 C# 中的装箱与拆箱 装箱:将一个数据项(副本)从栈中自动复制到堆中的行为. int i = 8; object o = i; // 装箱 // 首先在堆中开辟出一片区域,再将 ...
- Linux环境变量的设置和查看方法
1. 显示环境变量HOME $ echo $HOME /home/redbooks 2. 设置一个新的环境变量hello $ export HELLO="Hello!" $ ech ...