以前编写程序从没有做过单元测试的工作,所以在后期会花很多时间去纠错,这也就是软件工程中的2:8定律。最近要完成一个项目,要求要对系统中的主类和主函数作出单元测试的保证,才去查找了相关方面的资料,看过后觉得单元测试在工程中是必不可少的一项,下面就对有关C++的单元测试做一个简单的介绍,因为本人还没有系统的去理解相关方面的内容,所以只是介绍一些简单的应用和浅显的原理,有不到之处还请指出:

1) 什么是单元测试

单元测试(unit test,模块测试又称白盒测试)是开发者编写的一小段代码,用于检测被测代码的一个很小的,很明确的功能是否正确,通过编写单元测试可以在编码阶段发现程序编码错误,甚至是程序设计错误。现在回想下我们平时编程的过程:梳理逻辑->编写代码->调bug的一个循环过程;其中调试bug是一个很耗费时间的过程,而且调完一堆bug后我们对自己程序的信任度却在不断降低,因为不知道还会不会出bug。这是因为我们所调试的bug只是当前出现的,没有出现的呢,我们就说不好了。我们知道程序中一个简单的if...else...语句都会对数据流有一次分类,不同类的数据流所对应的操作不同,想想这些你就会觉得自己的代码还不知道要出多少bug。单元测试却很好的解决了这个问题,你要做的就是对核心的函数,核心的逻辑,将所有可能的数据流都列出来,进行一次全覆盖测试,这样你代码的健壮性就会很强。

2)如何写单元测试

最简单的方法那就是自己将核心的函数抽出来,重新建立一个项目,提供所有可能的数据流入口,对函数进行测试。这样做有两个缺陷:1、只能处理一些简单的项目,对于逻辑较为复杂,数据分支较多的就无法操作了;2、没有一个很好的框架,写出的代码没有一个统一的规则,可读性不强;为此,依托一个现有的测试框架是必不可少的。CppUnit是xunit家族的一员,xunit是一种测试框架,最早是在smalltalk上实现,后来被广泛的在各种语言上实现,除了Cppunit还有NUnit(c#版本)phpunit(php版本)和CppUnit相似的gtest(google的C++测试工具,据说在应用上要优于CppUnit,没有用过,大家可以试试),cmockery(c语言测试工具,也是google的)。cppunit以源码的方式发布,所以想要使用这个工具就要自己下载编译(后面会介绍到),同时在windows下CppUnit还带了一个MFC项目,可以以图形界面的方式报告编译情况。

3)如何编译CppUnit

我的编译环境是win7,vs2010;

1 :下载源码包 最新的版本是1.21.1(2008年最后一次更新)

地址 :http://sourceforge.net/projects/cppunit/ 或者直接点击 http://sourceforge.net/projects/cppunit/files/cppunit/1.12.1/cppunit-1.12.1.tar.gz/download

2 : 复制cppunt-1.12.1到c:\解压得到目录C:\cppunit-1.12.1

3 : 进入C:\cppunit-1.12.1\src 用VS2010打开CppUnitLibraries.dsw提示转换,转换之

4 : 在项目列表看见一堆项目,默认是以Debug的方式编译,如以该方式编译需要修改目标文件名

cppunit                $(ProjectName)   ->   $(ProjectName)d
cppunit_dll           $(ProjectName)   ->   cppunitd_dll
DllPlugInTester     $(ProjectName)   ->   $(ProjectName)d_dll
TestPlugInRunner $(ProjectName)   ->   $(ProjectName)d
TestRunner          $(ProjectName)  ->   $(ProjectName)d

需要修改目标文件名的原因是上述项目都设置了生成事件,在生成以后都会把生成的文件复制到lib目录下,个人判断d应该是代表了测试版的意思,如果是Release版本生成的目标文件都是项目名不需要修改

5 : 修改DSPlugIn入口
属性,配置属性,链接器,高级,无入口点 设置是

6 : 修改无法加载类型库(编译TestPlugInRunner,TestRunner)会报错其中7.0修改为8.0
#import "libid:80cc9f66-e7d8-4ddd-85b6-d9e6cd0e93e2" version("7.0") lcid("0") raw_interfaces_only named_guids

以上设置都全做完以后就可以整体编译解决方案了(这里要注意一点,要将上述所有的配置实现后再编译,不要对每个项目进行单独编译;否则会出现诸如“该文件没有一个关联的程序...”这样的问题)

4)如何用Cppunit

先写一个测试的Demo,初步体验下Cppunit的用法

1、打开vs2010文件项, 新建VC++空项目:cppUnitTest

2、 设置环境变量;在系统变量PATH的尾巴上添加“C:\cppunit-1.12.1”(这是我的地址)

3、 [项目cppUnitTest]-[属性]-[配置属性]-[C/C++]-[常规]-[附加包含目录]: "../include"

4、 [项目cppUnitTest]-[属性]-[配置属性]-[链接器]-[常规]-[附加库目录]: "../lib"

5、 [项目cppUnitTest]-[属性]-[配置属性]-[链接器]-[输入]-[附加依赖项]: "cppunitd.lib"

6、新建文件main.cpp

#include <cppunit/TestCase.h>
#include <cppunit/TestResult.h>
#include <cppunit/TestResultCollector.h>
#include <cppunit/TextOutputter.h>
#include <cppunit/TestCaller.h>
#include <cppunit/TestRunner.h> // 定义测试类
class StringTest : public CppUnit::TestFixture
{
public:
void setUp() // 初始化
{
m_str1 = "Hello, world";
m_str2 = "Hi, cppunit";
} void tearDown() // 清理
{
} void testSwap() // 测试方法1
{
std::string str1 = m_str1;
std::string str2 = m_str2;
m_str1.swap(m_str2); CPPUNIT_ASSERT(m_str1 == str2);
CPPUNIT_ASSERT(m_str2 == str1);
} void testFind() // 测试方法2
{
int pos1 = m_str1.find(',');
int pos2 = m_str2.rfind(','); CPPUNIT_ASSERT_EQUAL(, pos1);
CPPUNIT_ASSERT_EQUAL(, pos2);
} protected:
std::string m_str1;
std::string m_str2;
}; int main(int argc, char* argv[])
{
CppUnit::TestResult r;
CppUnit::TestResultCollector rc;
r.addListener(&rc); // 准备好结果收集器 CppUnit::TestRunner runner; // 定义执行实体
runner.addTest(new CppUnit::TestCaller<StringTest>("testSwap", &StringTest::testSwap)); // 构建测试用例1
runner.addTest(new CppUnit::TestCaller<StringTest>("testFind", &StringTest::testFind)); // 构建测试用例2
runner.run(r); // 运行测试 CppUnit::TextOutputter o(&rc, std::cout);
o.write(); // 将结果输出 return rc.wasSuccessful() ? : -;
}

以上代码时使用Cppunit框架对string类的两个函数进行测试,在testFind()中调用string的find函数并通过CPPUNIT_ASSERT对结果进行测试;

C++之单元测试的更多相关文章

  1. Intellij idea添加单元测试工具

    1.idea 版本是14.0.0 ,默认带有Junit,但是不能自动生成单元测试,需要下载JunitGererator2.0插件 2.Settings -Plugins,下载 JunitGenerat ...

  2. Python的单元测试(二)

    title: Python的单元测试(二) date: 2015-03-04 19:08:20 categories: Python tags: [Python,单元测试] --- 在Python的单 ...

  3. Python的单元测试(一)

    title: Python的单元测试(一) author: 青南 date: 2015-02-27 22:50:47 categories: Python tags: [Python,单元测试] -- ...

  4. javascript单元测试框架mochajs详解

    关于单元测试的想法 对于一些比较重要的项目,每次更新代码之后总是要自己测好久,担心一旦上线出了问题影响的服务太多,此时就希望能有一个比较规范的测试流程.在github上看到牛逼的javascript开 ...

  5. 使用NUnit为游戏项目编写高质量单元测试的思考

    0x00 单元测试Pro & Con 最近尝试在我参与的游戏项目中引入TDD(测试驱动开发)的开发模式,因此单元测试便变得十分必要.这篇博客就来聊一聊这段时间的感悟和想法.由于游戏开发和传统软 ...

  6. 我这么玩Web Api(二):数据验证,全局数据验证与单元测试

    目录 一.模型状态 - ModelState 二.数据注解 - Data Annotations 三.自定义数据注解 四.全局数据验证 五.单元测试   一.模型状态 - ModelState 我理解 ...

  7. ABAP单元测试最佳实践

    本文包含了我在开发项目中经历过的实用的ABAP单元测试指导方针.我把它们安排成为问答的风格,欢迎任何人添加更多的Q&A's,以完成这个列表. 在我的项目中,只使用传统的ABAP report. ...

  8. python_单元测试unittest

    Python自带一个单元测试框架是unittest模块,用它来做单元测试,它里面封装好了一些校验返回的结果方法和一些用例执行前的初始化操作. 步骤1:首先引入unittest模块--import un ...

  9. .Net中的AOP系列之《单元测试切面》

    返回<.Net中的AOP>系列学习总目录 本篇目录 使用NUnit编写测试 编写和运行NUnit测试 切面的测试策略 Castle DynamicProxy测试 测试一个拦截器 注入依赖 ...

  10. React单元测试——十八般兵器齐上阵,环境构建篇

    一个完整.优秀的项目往往离不开单元测试的环节,就 github 上的主流前端项目而言,基本都有相应的单元测试模块. 就 React 的项目来说,一套完整的单元测试能在在后续迭代更新中回归错误时候给与警 ...

随机推荐

  1. asp.net笔记

    1.  复习 a)         WebForm前后台页面(aspx, aspx.cs)文件在被访问时,会被编译成类,前台类继承于后台类 b)         被访问时,服务器会创建[前台页面类]对 ...

  2. SqlBulkCopy 类

    1.SqlBulkCopy 简介  Microsoft SQL Server 提供一个称为 bcp 的流行的命令提示符实用工具,用于将数据从一个表移动到另一个表(表既可以在同一个服务器上,也可以在不同 ...

  3. C# 计划任务

    计划任务 :  个人理解, 就是后台控制程序要求在一定的时间执行相应的任务. 直接上代码: 之前,因为工作需要. 要求每天在凌晨2:00,执行要做的数据 1.1  声明一个接口 Ijob 方法: 执行 ...

  4. HDU1242 Rescue(BFS+优先队列)

    Rescue Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Subm ...

  5. openstack configure

    <一,nova.conf配置文件配置 hypervisors compute_driver = 值> 1,kvm/qemu Hypervisor OpenStack nova comput ...

  6. python-MySQL库简单安装

    1  raise EnvironmentError("%s not found" % (mysql_config.path,)) EnvironmentError: mysql_c ...

  7. 【bzoj1031】[JSOI2007]字符加密Cipher

    题目描述 喜欢钻研问题的JS同学,最近又迷上了对加密方法的思考.一天,他突然想出了一种他认为是终极的加密办法:把需要加密的信息排成一圈,显然,它们有很多种不同的读法.例如下图,可以读作:JSOI07 ...

  8. Scala--样例类(case)详解

    概述: case类在模式匹配和actor中经常使用到,当一个类被定义成为case类后,Scala会自动帮你创建一个伴生对象并帮你实现了一系列方法且带来了不少好处,如下: 1.实现了apply方法,意味 ...

  9. linux 在批处理中,完整路径有空格的处理方式(加引號)

    cp -f E:/XML_EDITOR/xmleditor25/xmleditor/Editor_UIOuterCtrl/TraceViewDlg.cpp E:/XML_EDITOR/'XMLEdit ...

  10. 【git学习二】git基础之git管理本地项目

    1.背景        git基础打算分两部分来说,一部分是对于本地项目的管理,第二部分是对于远程代码仓库的操作. git运行本地项目管理包含对于相关文件的追踪,暂存区的比較分析,提交,撤销等功能. ...