用 GTest 来测试MFC 程序 TDD开发

无意间发现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。用 GTest 来测试MFC 程序 TDD开发_第1张图片

用 GTest 来测试MFC 程序 TDD开发_第2张图片

编译两次Solution,生成gtest-1.3.0\msvc\Debug-MDd 和gtest-1.3.0\msvc\Debug-MTd

用 GTest 来测试MFC 程序 TDD开发_第3张图片

用 GTest 来测试MFC 程序 TDD开发_第4张图片

在工程中使用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 就是用来创建一个控制台对象并注册为默认控制台。代码如下:

view plain copy to clipboard print ?
  1. class CConsole
  2. {
  3. public:
  4. CConsole(void);
  5. virtual ~CConsole(void);
  6. private:
  7. };
  8. #include "StdAfx.h"
  9. #include "Console.h"
  10. #include
  11. #include
  12. #include
  13. CConsole::CConsole(void)
  14. {
  15. AllocConsole();
  16. int hCrun;
  17. hCrun = _open_osfhandle((long)GetStdHandle(STD_OUTPUT_HANDLE), _O_TEXT);
  18. FILE* hFile = _fdopen(hCrun, "w");
  19. // use default stream buffer
  20. setvbuf(hFile, NULL, _IONBF, 0);
  21. *stdout = *hFile;
  22. //test
  23. //_cprintf("test console by _cprintf\n", 0);
  24. //std::cout << "test console by std: ut\n";
  25. }
  26. CConsole::~CConsole(void)
  27. {
  28. FreeConsole();
  29. }

测试执行完成以后,把Console窗口移到前台,并通过MessageBox阻止程序退出,便于查看控制台的输出。

运行结果

总结:

就本人的肤浅认识,与CPPUnit做个简单的对比

  • 优点:

使用方便,CPPUNIT需要添加好几个包含文件,需要手工声明测试套,这一点继承的GOOGLE的简洁作风测试用例。

  • 据点:

目前还没有发现GOOGLE GTEST有GUI的显示,也没有灵活的方式可以让用户选择部分测试用例执行。这一点没有CppUnit灵活。

所以,我还是暂时继续使用CPPUnit吧。

参考文献:

  1. Google C++ Testing Framework http://code.google.com/p/googletest/

  2. CoderZh 玩转Google开源C++单元测试框架Google Test系列 http://www.cnblogs.com/coderzh/archive/2009/04/06/1426755.html

  3. eyeblue 图解MFC程序中使用Google单元测试工具GTest进行TDD开发 http://blog.csdn.net/eyeblue/archive/2009/07/08/4332270.aspx

This entry was posted in Computer Tech and tagged GTEST MFC TDD. Bookmark the permalink. 编辑

你可能感兴趣的:(软件测试)