1. 程式人生 > >圖解MFC程式中使用Google單元測試工具GTest進行TDD開發(轉載)

圖解MFC程式中使用Google單元測試工具GTest進行TDD開發(轉載)

Google釋出了很多開源的軟體,最近嘗試了一下Google的單元測試工具 GTest,發現很有特色。這裡 有 個不錯的入門教程。GTest有個特色很有意思就是測試方法不需要在標頭檔案定義,直接把實現寫在程式碼裡面就行了。寫好的測試用例(其實就是一個過程)自動 註冊到單元測試引擎,不需要手工註冊。但GTest在結果呈現方面比較弱,我所知道只有命令列輸出和XML輸出。CppUnit在這方面明顯強很多,有個 UI工具可用來選擇執行測試用例並展示結果。回到GTest,本著方便實用的原則,首選當然是命令列輸出了,XML輸出等專案大了再用吧。

前面提到的教程是基於SDK的,而在MFC GUI程式下面使用GTest還是有些區別的,好了,廢話少說,Action!

一,編譯GTest庫檔案

首先我們需要為MFC編譯GTest庫。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

 

二,新建一個MFC專案

再次開啟Configuration Manager,從Debug配置複製一份新配置起名為Debug-Test, 然後設定專案配置

 新增gtest-1.3.0/include 到專案的標頭檔案路徑裡,並設定一個預定義GTEST

 

三,到 xxxxApp::InitInstance() 新增程式碼,把測試啟動程式碼和MFC程式啟動程式碼分開 , 這樣以後選擇Debug就是普通模式下執行MFC程式,選擇Debug-Test就是執行測試用例。如圖:

  1. BOOL  CPockerClientApp::InitInstance()  
  2. {  
  3. #ifdef GTEST
  4.     CConsole cc;  
  5.     int  argc = 0;  
  6.     TCHAR * argv = _T( "" );  
  7.     testing::InitGoogleTest(&argc, &argv);  
  8.     RUN_ALL_TESTS();  
  9.     HWND  hwnd = GetConsoleWindow();  
  10.     SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);  
  11.     AfxMessageBox(_T("about to exit!" ));  
  12.     return false ;  
  13. #else
  14.     // 如果一個執行 在 Windows XP 上的應用程式清單指定要
  15.     // 使用 ComCtl32.dll 版本 6 或更高版本來啟用 視覺化方式,
  16.     //則需 要 InitCommonControlsEx()。否則,將無法建立視窗。
  17.     INITCOMMONCONTROLSEX InitCtrls;  
  18.     InitCtrls.dwSize = sizeof (InitCtrls);  
  19.     // 將它設定為包括所有要在應用程式中使用的
  20.     // 公共控制元件類。
  21.     InitCtrls.dwICC = ICC_WIN95_CLASSES;  
  22. ......  
  23. ......  
  24.     // 唯一的一個視窗已初始化,因此顯示它並對其進行更新
  25.     m_pMainWnd->ShowWindow(SW_SHOW);  
  26.     m_pMainWnd->UpdateWindow();  
  27.     // 僅當具有後綴時才調 用 DragAcceptFiles
  28.     //  在 SDI 應用程式中,這應 在 ProcessShellCommand 之後發生
  29.     return  TRUE;  
  30. #endif //GTEST
  31. }  
BOOL CPockerClientApp::InitInstance() { #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 // 如果一個執行在 Windows XP 上的應用程式清單指定要 // 使用 ComCtl32.dll 版本 6 或更高版本來啟用視覺化方式, //則需要 InitCommonControlsEx()。否則,將無法建立視窗。 INITCOMMONCONTROLSEX InitCtrls; InitCtrls.dwSize = sizeof(InitCtrls); // 將它設定為包括所有要在應用程式中使用的 // 公共控制元件類。 InitCtrls.dwICC = ICC_WIN95_CLASSES; ...... ...... // 唯一的一個視窗已初始化,因此顯示它並對其進行更新 m_pMainWnd->ShowWindow(SW_SHOW); m_pMainWnd->UpdateWindow(); // 僅當具有後綴時才呼叫 DragAcceptFiles // 在 SDI 應用程式中,這應在 ProcessShellCommand 之後發生 return TRUE; #endif //GTEST }

四,定義了一個CConsole 例項。

因為MFC GUI程式預設是沒有控制檯的,所以我們就看不到GTest的輸出。CConsole 就是用來建立一個控制檯物件並註冊為預設控制檯。程式碼如下:

  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 <conio.h>
  11. #include <fcntl.h>
  12. #include <io.h>
  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::out/n";
  25. }  
  26. CConsole::~CConsole(void )  
  27. {  
  28.     FreeConsole();  
  29. }  

測試執行完成以後,把Console視窗移到前臺,並通過MessageBox阻止程式退出,便於檢視控制檯的輸出。

五,輸出效果

怎麼樣,還不錯吧。順便說一下本文說的MFC程式指GUI MFC Dialog程式或Document View程式,不包括MFC控制檯程式 :P

六,補記

使用TDD開發方法意味著需要頻繁執行測試,建議大家在自己VS的介面上新增一個Start Without Debug的圖示,知道怎麼做吧,我就不多說了。

七,再補

這段時間試用下來發現GTest不能選擇部分測試用例單獨測試挺不爽的,特別是寫了好多測試用例,這些用例都依賴了具體實現的某個方法,但只有其中 幾個Fail了,這種情況下debug就太麻煩了,雖然可以用條件斷點之類的手段,畢竟沒有CPPUnit那樣按需選擇方便。從這個角度看,GTest還 不適合在測試用例比較多的專案中應用。

轉載自:http://blog.csdn.net/eyeblue/archive/2009/07/08/4332270.aspx