51Testing软件测试论坛
标题:
使用CppUnit进行单元测试(详细步骤)
[打印本页]
作者:
蓝柚
时间:
2006-4-18 09:54
标题:
使用CppUnit进行单元测试(详细步骤)
一. CppUnit的安装
从
http://sourceforge.net/projects/cppunit
CppUnit的源码包. CppUnit是开源产品 , 当前最高版本为1.11.0. (在上面的链接所指向的页面上选择 Development Snapshot ).
下载后,将源码包解压缩到本地硬盘. 以C:为例, 解压到C:\CppUnit-1.11.0 . 接下来进行编译工作. 在src/目录下, 将CppUnitLibraries.dsw工程文件用vc 打开. 因为这个工程是vc6建的工程, 所以会提示是否将此工程转为vc.net的工程格式. 选择"全是"就行. 然后在"生成"菜单中选择"生成解决方案",编译整个工程.
编译通过以后, 在lib/目录下,会生成若干lib,和dll文件, 都以cppunit开头. cppunitd表示debug版, cppunit表示release版.
然后配置vc环境: 工具菜单->选项->项目->vc++目录, 将C:\cppunit-1.11.0\include加入到vc 的 头文件目录中. 将C:\cppunit-1.11.0\lib 加入到vc的 连接库目录中. 然后将 C:\cppunit-1.11.0\lib路径加入到系统路径中(因为我们的测试程序需要cppunit的dll文件,所以要dll所在路径加入到系统路径(path)变量中, 或者将这些文件拷贝到系统目录中也可以).
二. CppUnit 的使用
以上工作完成以后,就可以正式使用CppUnit了.
我们新建一个控制台工程, 假定工程名为TDD1. 假设我们将在这个工程下开发, 那么根据测试驱动的原理,我们需要先建立一个单元测试框架. 在CppUnit下, 可以选择控制台方式和UI方式两种表现方案.我们选择UI方式. 那么现在在原来工程的基础上,再新增加一个对话框工程. 假设名为:Unit_Test .
在CppUnit中, 是以TestCase为最小的测试单位, 若干TestCase组成一个TestSuite. 所以我们要先建立一个TestCase.
新建一个类, 命名为CTestCase , 让其从CppUnit::TestCase派生. 为其新增一个方法,假设为 void doTest(); 我们将在这个函数中写入我们的一些测试代码. 切记要包含头文件
#include <CppUnit/extensions/HelperMacros.h>
class CTestCase : public CppUnit::TestCase
{
public:
CTestCase(void);
~CTestCase(void);
void doTest();
};
接下来, 我们要对我们的TestCase进行声明. 声明用到了三个宏.
CPPUNIT_TEST_SUITE();
CPPUNIT_TEST();
CPPUNIT_TEST_SUITE_END();
第一个宏声明一个测试包,第二个宏声明一个测试用例. 现在我们的CTestCase类看上去象这样.
class CTestCase : public CppUnit::TestCase
{
CPPUNIT_TEST_SUITE(CTestCase);
CPPUNIT_TEST(doTest);
CPPUNIT_TEST_SUITE_END();
public:
CTestCase(void);
~CTestCase(void);
void doTest();
};
接下来,我们要注册我们的测试suite. 使用CPPUNIT_TEST_SUITE_NAMED_REGISTRATION()来注册一个测试suite. 这个宏的第二个参数是我们注册的suite的名字. 在这里我们可以用字符串来代替, 但我们用一个静态函数来返回这个suite的名字.
//TestCase.h
static std::string getSuiteName();
//TestCase.cpp
std::string CTestCase::getSuiteName()
{
return "TDDExample3";
}
记得要在TestCase.h中包含 #include <string>
然后在 TestCase.cpp注册我们的suite.
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(CTestCase , CTestCase::getSuiteName() );
接下来我们写一个注册函数, 使其在运行期生成一个Test.
static CppUnit::Test* getSuite();
CppUnit::Test* CTestCase::getSuite()
{
CppUnit::TestFactoryRegistry& reg =
CppUnit::TestFactoryRegistry::getRegistry ( CTestCase::getSuiteName() );
return reg.makeTest();
}
记住包含头文件:
#include <cppunit/extensions/TestFactoryRegistry.h>
最后, 我们的单元测试建立一个UI测试界面.
我们在CUnit_TestApp::InitInstance()函数中,将原先显示主对话框的代码以下面的代码取代:
CppUnit::MfcUi::TestRunner runner;
runner.addTest(CTestCase::getSuite());
runner.run();
必须先包含头文件:
#include <cppunit/ui/mfc/TestRunner.h>
#include "TestCase.h"
到此为止, 我们已经建立好一个简单的单元测试框架. 我们可以在doTest()中加入我们的测试代码,来进行测试了. CppUnit会将测试结果通过一个界面显示出来.
但此时我们虽然能编译通过,但在连接时会发生错误. 所以将下面两个库加入到工程中. 也可以在TestCase.h 中显式的加入:
#pragma comment(lib,"cppunit.lib")
#pragma comment(lib,"testrunnerd.lib")
下面是完整的程序清单:
//TestCase.h
#pragma once
#include <string>
#include <CppUnit/extensions/HelperMacros.h>
#include <cppunit/extensions/TestFactoryRegistry.h>
#include <cppunit/Asserter.h>
#pragma comment(lib,"cppunit.lib")
#pragma comment(lib,"testrunnerd.lib")
class CTestCase : public CppUnit::TestCase
{
CPPUNIT_TEST_SUITE(CTestCase);
CPPUNIT_TEST(doTest);
CPPUNIT_TEST_SUITE_END();
public:
static std::string getSuiteName();
static CppUnit::Test* getSuite();
public:
CTestCase(void);
~CTestCase(void);
void doTest();
};
//TestCase.Cpp
#include "StdAfx.h"
#include ".\testcase.h"
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(CTestCase , CTestCase::getSuiteName() );
CTestCase::CTestCase(void)
{
}
CTestCase::~CTestCase(void)
{
}
void CTestCase::doTest()
{
}
std::string CTestCase::getSuiteName()
{
return "TDDExample3";
}
CppUnit::Test* CTestCase::getSuite()
{
CppUnit::TestFactoryRegistry& reg =
CppUnit::TestFactoryRegistry::getRegistry( CTestCase::getSuiteName() );
return reg.makeTest();
}
//Unit_Test.cpp
#include <cppunit/ui/mfc/TestRunner.h>
#include "TestCase.h"
BOOL CUnit_TestApp::InitInstance()
{
InitCommonControls();
CWinApp::InitInstance();
AfxEnableControlContainer();
CppUnit::MfcUi::TestRunner runner;
runner.addTest(CTestCase::getSuite());
runner.run();
return FALSE;
}
现在编译,运行, 如图一:
进度条呈现绿色, 表示我们此次测试通过. 事实上我们的doTest是一个空函数,什么代码也没有写,当然能通过了. :)
下面我们在doTest()中加点代码进去.
char* p = NULL; p[0]='c';
这段代码会引起一个访问异常. 看UnitCpp怎么来报告这段代码的错误.
编译,运行如图2:
这时CppUnit会告诉我们dotest出现一个错误. 并提供了错误的一些信息.
这样我们用CppUnit搭建一个简单单元测试框架.
作者:
蓝柚
时间:
2006-4-18 09:56
上面程序已经过验证,但也只是简单介绍下框架,希望对大家有些帮助~!
作者:
zx116_2000
时间:
2006-4-18 15:02
谢谢!
我VC版本是:Visual C++ 2005 Express Edition
可编绎 CppUnit-1.11.0时,编绎失败,
D:\Program Files\Microsoft Visual Studio 8\VC\include\xlocinfo.h(6) : fatal error C1083: Cannot open include file: 'locale.h': No such file or directory TestResultCollector.cpp
这是编绎失败的相关信息~
作者:
zixuxuwu
时间:
2006-4-18 20:52
找个安装包,把这个文件拷到你的安装目录下。
作者:
天生我才
时间:
2006-4-24 08:21
谢谢斑竹了
作者:
男孩子
时间:
2006-11-7 10:53
楼主的文章写得非常棒,可是有一处搞不清楚:
“我们新建一个控制台工程, 假定工程名为TDD1. 假设我们将在这个工程下开发, 那么根据测试驱动的原理,我们需要先建立一个单元测试框架. 在CppUnit下, 可以选择控制台方式和UI方式两种表现方案.我们选择UI方式. 那么现在在原来工程的基础上,再新增加一个对话框工程. 假设名为:Unit_Test . ”
控制台工程中如何增加一个对话框工程呢?VC学的不好,见笑。
作者:
VisualUnit
时间:
2006-11-7 11:05
楼主的原意大概是在workspace中增加一个对话框工程,表达稍有点不清,呵呵。
产品工程是TDD1,新建一个测试工程Unit_Test,大概是这意思。
作者:
男孩子
时间:
2006-11-8 11:49
唉,水平有限,还是不知道怎么弄。
谢谢楼上提醒了,按照你讲的做有些眉目了,但是编译有问题,不知道怎么回事。
作者:
VisualUnit
时间:
2006-11-8 12:53
标题:
to 男孩子
还是用Visual Unit吧,要简单好用高效得多,中文资料齐全,包括视频教程,还有在线技术支持。免费的版本(个人版)也挺好用的,仅自动生成测试代码这一项就至少可以减少百分之七十的测试时间。
很多人以为自动生成测试代码不如手工编写灵活,其实这是误解。因为:
VU生成的测试代码是透明的,需要时可以修改;
VU具有自定义测试功能,这里就是由用户自行编写测试代码的,不过一般的测试是用不上的,主要用于特殊需求如对已编译好的DLL或COM组件的测试;
VU不需要由测试代码来进行测试组织,因此测试代码更简单,简单就意味着灵活;
预期输出是很重要的部分,CPPUNIT是一堆宏,VU只使用一个宏,既简单又灵活,如下面的预期输出都是可以的:
strcmp(str, "abce") == 0 //判断两个字符串是否相等
.m_strName.IsEmpty() //用.操作符直接访问成员变量,可以直接调用返回值为布尔类型的函数
ret > 0 || a <0 //复合表达式也行
对于第一和第三个例子,CPPUNIT要使用中间变量才行。
至于其他优点,因不具有可比性,我就不说了。我建议您两种都试试,有比较才分得清优劣。
官方网站
http://www.KaileSoft.cn
[
本帖最后由 VisualUnit 于 2006-11-8 13:01 编辑
]
作者:
男孩子
时间:
2006-11-8 13:28
to:VisualUnit
我现在学习CppUnit是公司指定的,没有自主选择的权利。所以还是谢谢你的好意了。
作者:
华人天堂
时间:
2006-12-31 09:55
我现在在公司学这两个工具,再要我选一个拿来用,我是想用Visual unit的,不用编程,对做测试的我来说,倒是方便的,比楼上那哥们要好点
作者:
alina_zh
时间:
2007-3-27 00:01
我在安装CPPUnit时,发现一个错误提示:
Error executing c:\windows\system32\cmd.exe
系统目录下cmd.exe是存在的啊~~
不知道这个错误问题大不大,该怎么改呢?
编译设置完后,我建了一个测试环境来试着测一个小程序,可是编译时提示:
F:\ResourceCode\test\test compare\main.cpp(10) : error C2039: 'TextUi' : is not a member of 'CppUnit'
F:\ResourceCode\test\test compare\main.cpp(10) : error C2065: 'TestRunner' : undeclared identifier
这是怎么回事儿呢?与上面提到的安装时的错误有关吗??
作者:
changing
时间:
2009-5-26 11:59
标题:
救救
请问,debug和release的设置分别是什么?
我总出现错误:LINK : fatal error LNK1104: cannot open file "..TDD1\unit_test1\Debug/cppunitd.lib"
Error executing link.exe.
我的设置的project--settings--C/C++页面信息如下:
Output file name: ..\TDD1\unit_test1\Debug/unit_test1.exe
Object/library modules: ..\TDD1\unit_test1\Debug/cppunitd.lib ..\TDD1\unit_test1\Debug/testrunnerd.lib
我的这两个文件已经放在debug目录下了,还是一样出错误!
欢迎光临 51Testing软件测试论坛 (http://bbs.51testing.com/)
Powered by Discuz! X3.2