CppUnit是一个开源的、跨平台的用于C++的单元测试工具。本文以VC6和VC8为例,简单介绍其使用方法。 首先,到http:///project/showfiles.php?group_id=11795下载回CppUnit的最新源代码(当前最新版1.12.0)和文档。将源码包解压,在源代码包子目录src下已经配置好了VC6的工程文件。 如果使用VC6,那么直接用VC6打开VC工程文件,选择Batch Build(最好自己对工程参数重新设置一下),然后就可以在源代码包子目录Lib中得到我们需要的库文件。如果使用VC8,那么用VC8打开VC6工程 文件,并按提示直接转换成.net版本。同样,选择批生成,生成我们需要的库文件。在VC8中编译源代码时会出现编译错误“#import "libid:80cc9f66-e7d8-4ddd-85b6-d9e6cd0e93e2" version("7.0") lcid("0") raw_interfaces_only named_guids”,将version("7.0")改为version("8.0")即可。 在开发应用程序过程中,我们可能会使用到很多第三方程序库,如这里的CppUnit。为了方便,我们可以建立一个第三方程序库的专用文件夹,并为具体的程 序库(如这里的CppUnit)建立子文件夹。然后在VC的Option中分别设置库的头文件路径和库文件连接路径。如果有Dll文件,则在系统变量 PATH中加进DLL文件所在目录,这样,程序运行时就能搜索到该DLL文件并加载(注意,只有VC重启后,PATH设置才会对从VC里直接运行的程序生 效)。同样,这里我们也把CppUnit的头文件和库文件路径加到VC的默认搜索路径中。 另外,需要指出,一般情况下,Dll文件是需要与生成的程序一同发布的,此时就必须将Dll文件拷贝到Project目录中。此时,可以采取手动方式,也可以在Project的Post-Build Step中添加命令执行拷贝动作。 在VC中使用CppUnit进行单元测试时,可以选择CppUnit的控制台测试作界面和图形测试界面。控制台界面简洁,而图形界面较直观,并且借助 CppUnit提供的插件可以快速定位到断言失败的地方。一般情况下,我们使用控制台测试界面来测试Console程序,使用图形测试界面来测试GUI程 序,这样测试Project不会影响被测试的Project。由于图形测试界面的易用性,我们可能也希望用它来测试Console程序,此时稍微麻烦一 点。下面分别介绍这几种用法(以VC6为例,VC8类似)。 在下面的叙述中,把被测试Project叫做目标Project,把被测试类叫做目标类。 ****** 使用CppUnit的Console测试界面测试Console程序 ****** 1. 创建一个工作区用于开发和测试,然后在该工作区中分别创建两个Project,一个用于开发,另一个用于测试。 2. 在测试Project中,设置如下: (1) 设置连接库:cppunit.lib(Release版)和 cppunitd.lib(Debug版),或者使用动态链接库版本cppunit_dll.lib、cppunit_dll.dll和 cppunitd_dll.lib、cppunitd_dll.dll; (2)在C/C++的Code Generation中设置Use run-time library为Multithreaded Dll(Release版)和Debug Multithreaded Dll(Debug版)。 3. 为测试Project添加测试类,假如被测试的目标类为Demo,那么可以定义一个DemoTest的测试类: 文件DemoTest.h: #ifndef DEMO_TEST_H #define DEMO_TEST_H #include "cppunit/extensions/HelperMacros.h" class DemoTest: public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(DemoTest); // 参数为本测试类名 CPPUNIT_TEST(testFunc); // 参数为测试函数名,与下面声明的测试函数对应 CPPUNIT_TEST_SUITE_END(); public: void setUp() { // 在这里进行测试的初始化工作 } void tearDown() { // 在这里进行测试完毕后的清理工作 } void testFunc(); // 测试函数,用来测试目标类的某一个细节 }; #endif // DEMO_TEST_H 文件DemoTest.cpp: #include "DemoTest.h" #include "../Demo/DemoTest.h" // 这里为要测试的目标类的头文件路径,因为测试时要用到Demo类 #include <cppunit/extensions/HelperMacros.h> CPPUNIT_TEST_SUITE_REGISTRATION(DemoTest); void DemoTest::testFunc() { // 这里对Demo类进行测试,可以使用CPPUNIT_ASSERT、CPPUNIT_ASSERT_EQUAL等来断言 } 4. 由于测试类中要用到目标类,所以需要把目标类的实现文件加入到测试Project中,但不用加入目标类的头文件,这样在测试Project中的类视图中就不会出现目标类。 5. 在测试Project中,新建一个源文件,用来写测试的main函数,测试框架如下: #include "DemoTest.h" #include <cppunit/extensions/TestFactoryRegistry.h> #include <cppunit/ui/text/TestRunner.h> int main() { CppUnit::TextUi::TestRunner runner; CppUnit::TestFactoryRegistry ®istry = CppUnit::TestFactoryRegistry::getRegistry(); runner.addTest(registry.makeTest()); runner.run(); return 0; } 6. 运行测试Project,就可以看到测试结果。在测试运行时,如果测试函数中某一断言失败,则此函数执行中断,此测试函数中后面的断言不会被执行。因此,应该尽可能压缩测试函数,使其测试功能单一。 7. 注意,在该测试方案中,并没有对被测试Project有任何要求或者修改。被测试Project可以是一个完整的工程(会生成自己的执行程序),也可以只是一个Dll Project或者仅有类的实现。 ****** 使用CppUnit的GUI测试界面测试GUI程序 ****** 1. 创建测试Project为基于Dialog的MFC Project。然后,设置测试Project的连接库cppunitd.lib和testrunnerd.lib(Debug版)(同样设置 Release版,选择相应版本库文件)。CppUnit的GUI版本还需要使用TestRunnerd.dll文件。如果在系统环境变量PATH中没有 TestRunner.dll文件所在目录,那么需要把TestRunnerd.dll文件拷贝到测试Project目录下。另外,这里不需要设置代码的 运行库,因为MFC Project默认就是Multithreaded Dll运行库。 2. 与Console测试方案一样,添加测试类。 3. 找到App类的InitInstance函数,把原来用于显示对话框的代码替换为如下代码: CppUnit::MfcUi::TestRunner runner; CppUnit::TestFactoryRegistry ®istry = CppUnit::TestFactoryRegistry::getRegistry(); runner.addTest(registry.makeTest()); runner.run(); //show UI 并加上头文件: #include <cppunit/extensions/TestFactoryRegistry.h> #include <cppunit/ui/mfc/TestRunner.h> 4. 此时,编译运行就可出现图形测试界面,在Browse里面选择要测试的树(在CppUnit中所以测试被组织为了颗树),然后点击Run即可运行测试。 5. 为了快速定位失败的断言,CppUni提供了专门的插件用于GUI方案,在VC6的Tools|Customize|Add-ins and Macro Files中添加CppUnit的TestRunnerDSPlugIn.dll。然后,双击失败的断言即可定位到相应的源代码。 ****** 使用CppUnit的GUI测试界面测试Console程序 ****** 由于GUI测试界面的易用性,我们可能也希望用它来测试Console程序。如果直接用上面的默认GUI方案去测试Console程序,则需要修改被测试 Project(要在源文件添加stdafx.h头文件),违背了测试的原则(被测试Project不应该感知测试Project的存在的)。为了解决这 个不足,同时仍保留GUI方案的直观性与方便性,我们可以定制自己的GUI测试方案。具体过程如下: 1. 同样,建立测试工作区,然后建立Console目标Project(被测试Project)和空的Win32(不是MFCProject!)测试 Project。然后,在测试Project的Project Setting中设置General为Use MFC in a Shared DLL,设置链接库cppunitd.lib testrunnerd.lib (Debug版)[将testrunnerd.dll拷贝到测试Project目录下]。 2. 同样,添加测试类。 3. 写一个TestApp类(可以用于所有测试,不用修改),如下: TestApp.h文件: #ifndef TEST_APP_H #define TEST_APP_H #include <afxwin.h> class TestApp: public CWinApp { public: virtual BOOL InitInstance(); }; #endif // TEST_APP_H TestApp.cpp文件: #include "TestApp.h" #include <cppunit/extensions/TestFactoryRegistry.h> #include <cppunit/ui/mfc/TestRunner.h> BOOL TestApp::InitInstance() { CppUnit::MfcUi::TestRunner runner; CppUnit::TestFactoryRegistry ®istry = CppUnit::TestFactoryRegistry::getRegistry(); runner.addTest(registry.makeTest()); runner.run(); //show UI return FALSE; } TestApp theApp; 4.然后,编译、运行程序即可。此时,测试Project不再需要被测试Project的源文件包含头文件stdafx.h。 ****** 建立Post-build测试机制 ******
如果我们希望程序编译完成后自动运行测试,那么我们就可以利用Post-build测试机制。 在VC6的Project|Settings对话框的Post-build step标签下,在Post-build command中添加一行:$(TargetPath),$(TargetPath)将展开为你的应用程序名(包括路径)。同时,修改程序的main函 数,如果main返回非0,则表示此“Build”失败;返回0表示成功。同样,在VC8中的工程设置中也有对应项供设置。 博主后一篇:C语言的可变参数(文章转,附件亲自制作) |
|