无意间发现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, 0, 0, 0, 0, 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 就是用来创建一个控制台对象并注册为默认控制台。代码如下:
测试执行完成以后,把Console窗口移到前台,并通过MessageBox阻止程序退出,便于查看控制台的输出。
运行结果
总结:
就本人的肤浅认识,与CPPUnit做个简单的对比
使用方便,CPPUNIT需要添加好几个包含文件,需要手工声明测试套,这一点继承的GOOGLE的简洁作风测试用例。
目前还没有发现GOOGLE GTEST有GUI的显示,也没有灵活的方式可以让用户选择部分测试用例执行。这一点没有CppUnit灵活。
所以,我还是暂时继续使用CPPUnit吧。