无意间发现GOOGLE发布了一个开源的C++单元测试框架 Google Test,称GTest。很多兄弟夸奖,对GOOGLE的东东还是很有兴趣。一时试了一下。 发现测试MFC没有那样方便,不过总是能用。
下载
http://code.google.com/p/googletest/
我下载的时候,版本为1.4
编译gtest库文件
首先我们需要为MFC编译GTest库。 gtest默认的工程配置中,动态库选项使用得是MT, 而我们一般使用的MFC程序是MD,关于这两个选项的详细区别大家参考 各种 C 运行时库的区别 。 这里我大概提一下,多的那个D代表动态。 特别注意的一点是,gtest生成库的这个选项 "Runtime Library"必须相同,否则会链接的时候出错。
所以我会生成两个库,一个是MD,另一个是MT。详细的操作:
是VS下面打开gtest工程文件,打开Configuration Manager,从Debug配置复制两份新配置,分别起名为 Debug-MDd 和 Debug-MTd. 然后到项目管理器里面重设所有项目的属性,如图分别设置相应的 Runtime Library。
编译两次Solution,生成gtest-1.3.0\msvc\Debug-MDd 和gtest-1.3.0\msvc\Debug-MTd
在工程中使用GTEST
假设你已经有一个MFC工程了。现在需要加入测试代码。
1.设置头文件, 让工程可以找到GTEST中定义的宏和类
在这里我多设置了一个宏,以便实现测试代码和正常调度代码的分离,作用后面再说
2.设置gtest.lib路径
其实这里有两种办法,一是 在本工程是同时插入GTEST工程,这样让工程依赖GTEST工程即可。
二是让现有工程包含gtest库。
作用基本一相,区别是依赖的时候,经常会重新编译gtest,但可以源代码级的跟踪。 包含刚好相反。我倒还没到分析GTEST源代码的时候,所以用第二种。
设置测试代码入口
CPPUNIT中,测试代码是一个单独的工程,按道理,GTEST也是如此,可是我发现在另一个工程中测试MFC工程中的程序时,需要添加很多头文件,而且还经常出错。也可能是那里我没有搞定。所以现在在同一个工程中进行。 这样唯一的好处是不需要处理那些麻烦的头文件,但从软件工程角度是没有好处的。
MFC程序都是GUI的,这时需要取消系统本有的GUI,而用GTEST的concle代替 入口地有两种,如果是Dialog 则是
×××::OnInitDialog()
如果是 D/VIEW则
xxxxApp::InitInstance()
在其中做如下修改:
//test project
#ifdef _GTEST
CConsole cc;
int argc = 0;
TCHAR* argv = _T("");
testing::InitGoogleTest(&argc,&argv);
RUN_ALL_TESTS();
HWND hwnd = GetConsoleWindow();
::SetWindowPos(hwnd,HWND_TOP,SWP_NOMOVE|SWP_NOSIZE);
AfxMessageBox(_T("about to exit!"));
return false;
#else
..... //这里是原有的程序
#endif
加入测试代码
//test code
TEST(DlgTest,simpleTest1)
{
CmyDlg myDlg;
int nCnt = 5;
myDlg.SetCnt(nCnt);
EXPECT_EQ(nCnt,myDlg.GetCnt()) ;
}
CConsole 是一个类,来实现控制台的输出
因为MFC GUI程序默认是没有控制台的,所以我们就看不到GTest的输出。CConsole 就是用来创建一个控制台对象并注册为默认控制台。代码如下:
- class CConsole
- {
- public:
- CConsole(void);
- virtual ~CConsole(void);
- private:
- };
- #include "StdAfx.h"
- #include "Console.h"
- #include <conio.h>
- #include <fcntl.h>
- #include <io.h>
- CConsole::CConsole(void)
- {
- AllocConsole();
- int hCrun;
- hCrun = _open_osfhandle((long)GetStdHandle(STD_OUTPUT_HANDLE),_O_TEXT);
- FILE* hFile = _fdopen(hCrun, "w");
- // use default stream buffer
- setvbuf(hFile,NULL,_IONBF,0);
- *stdout = *hFile;
- //test
- //_cprintf("test console by _cprintf\n",0);
- //std::cout << "test console by std: ut\n";
- }
- CConsole::~CConsole(void)
- {
- FreeConsole();
- }
测试执行完成以后,把Console窗口移到前台,并通过MessageBox阻止程序退出,便于查看控制台的输出。
运行结果
总结:
就本人的肤浅认识,与CPPUnit做个简单的对比
- 优点:
使用方便,CPPUNIT需要添加好几个包含文件,需要手工声明测试套,这一点继承的GOOGLE的简洁作风测试用例。
- 据点:
目前还没有发现GOOGLE GTEST有GUI的显示,也没有灵活的方式可以让用户选择部分测试用例执行。这一点没有CppUnit灵活。
所以,我还是暂时继续使用CPPUnit吧。
参考文献:
-
Google C++ Testing Framework http://code.google.com/p/googletest/
-
CoderZh 玩转Google开源C++单元测试框架Google Test系列 http://www.cnblogs.com/coderzh/archive/2009/04/06/1426755.html
-
eyeblue 图解MFC程序中使用Google单元测试工具GTest进行TDD开发 http://blog.csdn.net/eyeblue/archive/2009/07/08/4332270.aspx