- ãGoogle製ã®C++ Unit Test FrameworkãGoogle Testãã使ã£ã¦ã¿ããï¼CodeZineï¼
- google/googletestï¼GitHubï¼
Mockã¨ã¯
ãUnit Testã¯é常ä½ãã¬ã¤ã¤ã®é¢æ°ï¼ã¯ã©ã¹ããè¡ããã¾ããé¢æ°f()ããã¹ãããã¨ããf()ãg()ãå¼ãã§ãããªããã¾ãg()ããã¹ããã¦æ£ããåãã¦ããããã¨ã確èªãã¦ããã§ãªãã¨f()ãååã«ãã¹ãã§ãã¾ããã
ãã¨ãããããããªäºæ ã§g()ãæ£ããåä½ãããã¨ãæ¤è¨¼ã§ãã¬ã¾ã¾f()ããã¹ãããããå¾ãªããã¨ãããã¾ããä¾ãã°ã¹ã±ã¸ã¥ã¼ã«ã®é½åã§g()ã®å®æãããªãé ãããã¨ã«ãªã£ããã¨ããg()ã¯ãã¼ã¿ãã¼ã¹ã«ã¢ã¯ã»ã¹ãããã ãã©ããã®g()ããã¹ãã«ç¨ããã¨å¤§äºãªãã¼ã¿ãç ´å£ããããªããã¨ãããããã¯g()ã¯å®æãæ£ããåä½ãããã¨ã¯ç¢ºèªæ¸ã¿ã ãã©ã"ããã¨"ã¨ã©ã¼ãèµ·ãããã¨ã極ãã¦å°é£ï¼ãã¼ãã¦ã§ã¢ã®ãã©ãã«ã«èµ·å ããã¨ã©ã¼ã¨ãï¼ãªããã«ããããå¼ãã§ããf()ã®ç°å¸¸ç³»ã®ãã¹ããã§ããªããã¨ãã
ããããªã¨ãã«ä½¿ãããã®ãMockã§ããMockã¯ãã®ä¾ã§ããã°f()ããå¼ã°ããé¢æ°g()ã®ãã»ã¢ãï¼ããªããã§ãããããæ¬ç©ã®g()ã§ãããã®ããã«åä½ããããã¨ãã§ãã¾ããããã«Mocké¢æ°g()ã¯ãã®æåãå¤é¨ããã³ã³ããã¼ã«ã§ãã¾ããä¾ãã°f()ã®å é¨ããg()ãå¼ã°ããåã«"次ã®å¼ã³åºãæã«ã¯ããã¨ã¨ã©ã¼ãè¿ã"ã ã¨ã"æåã®2åã¯trueããã以éã¯falseãè¿ã"ã®ããã«ããããããMock-g()ã«ãã³ããªãä»è¾¼ãã§ããã¦ãã®ãã³ããªéãã«åå¿ããããã¨ã§f()ã®åä½ãæ£ãããããã¹ãã§ãã¾ããMockã¯ããã°"ããã°ã©ããã«ãªããªãã"ã¨ã§ãç³ãã¾ããããã
Mockã®ä½æ
ãgmockï¼Google Mockï¼ã®å³è¦ã«åãæããã¾ããããGitHubä¸ã®google testã«ããstable-releaseããrelease-1.8.0ã®ã½ã¼ã¹ã³ã¼ãï¼zipï¼ããã¦ã³ãã¼ãããé©å½ãªãã£ã¬ã¯ããªã«å±éãã¾ãï¼ãã®ãã£ã¬ã¯ããªã以é<gtest_root>ã¨è¡¨è¨ãã¾ãï¼ã
ãã³ãã³ãã©ã¤ã³ï¼Visual Studio ã³ãã³ãããã³ããï¼ãã<gtest_root>ã«ç§»åãã以ä¸ã®batchãå®è¡ãã¦ã©ã¤ãã©ãªãä½ãã¾ãï¼
:/ <GTEST_ROOT>ãé©å®æ¸ãæã㦠set GROOT=<GTEST_ROOT> set GT=%GROOT%\googletest set GM=%GROOT%\googlemock :/ âARCH㯠X86 or X64 set ARCH=X64 cl -c -MD -EHsc -I%GT%\include -I%GT% %GT%\src\gtest-all.cc %GT%\src\gtest_main.cc cl -c -MD -EHsc -I%GM%\include -I%GT%\include -I%GM% %GM%\src\gmock-all.cc %GM%\src\gmock_main.cc mkdir lib lib /OUT:lib\gtest.lib /MACHINE:%ARCH% gtest-all.obj lib /OUT:lib\gtest_main.lib /MACHINE:%ARCH% gtest_main.obj lib /OUT:lib\gmock.lib /MACHINE:%ARCH% gmock-all.obj lib /OUT:lib\gmock_main.lib /MACHINE:%ARCH% gmock_main.obj
ãgtestï¼gmockã®æºåã¯ããã§å®äºããã¹ãã®ã³ã³ãã¤ã«ï¼ãªã³ã¯æã¯include-pathã¯<gtest_root>\googletest\includeã¨<gtest_root>\googlemock\includeãlibrary-pathã¯<gtest_root>\libãè¨å®ããã©ã¤ãã©ãªgtest.libã¨gmock.libããªã³ã¯ãã¾ããã¤ãã§ã«gmock_main.libããªã³ã¯ããã¨main()ã®å®è£ ãè¦ããªããªãã¾ãã
ããã¦ã¨ãããããgmockã®ä½¿ãæ¹ããã¹ã対象ã®ãµã³ãã«ã¨ãã¦ãã¨ããå£åº§ï¼Accountã対象ã«è¤æ°ã®åå¼ï¼é å ¥ï¼å¼åºï¼ãä¸æ¬ãã¦è¡ãé¢æ°ï¼dealãç¨æãã¾ããã
#ifndef DEAL_H_ #define DEAL_H_ #include "Account.h" #include <queue> int deal(Account* acc, std::queue<int>& amounts); #endif
ãAccountã®ã¡ã³ãé¢æ°ã¯bool deposit(int amount)ã¨bool withdraw(int amount)ãããããå¼æ°ï¼amountã«ç¤ºãããé¡ã®é å ¥ã¨å¼åºãè¡ããæåï¼å¤±æã«å¿ãã¦trueï¼falseãè¿ãã¾ãããã ããamountã¯0ãã大ãããªãã¦ã¯ãªããªããã®ã¨ãã¾ãã
ãä¸é£ã®åå¼ãè¡ãé¢æ°ï¼dealã¯å¼æ°ï¼amountsããåå¼é¡ãä¸ã¤ãã¤åãåºãããããæ£ãªãé å ¥ï¼è² ãªãå¼åºãaccã«å¯¾ãã¦è¡ããåå¼ãæåããã°amountsããåãé¤ãã¾ãï¼åå¼é¡ã0ãªããªã«ãããåå¼æåæ±ãã¨ãã¾ãï¼ãéä¸ä¸åº¦ã§ãåå¼ã«å¤±æãããããã以éã®åå¼ãè¡ãã¾ãããdealã¯æåããåå¼ã®åæ°ãè¿ãã¾ããå¾ã£ã¦ä¾ãã°5ã¤ã®åå¼ãdealã«æ¸¡ãããã¨ããå ¨åå¼ãæåããã°amountsã¯ç©ºã«ãªãdealã¯5ãè¿ãã¾ãããæåã®åå¼ã失æããã°amountsã¯ãã®ã¾ã¾ã§0ãè¿ããã¨ã«ãªãã¾ãã
ãâ¦â¦ã¨ã以ä¸ã®ä»æ§ã«å¾ããªããååå¼ã®æåï¼å¤±æã«ãããããããdealåã®queueã®é·ãï¼dealã®æ»ãå¤ï¼dealå¾ã®queueã®é·ããã¨ãªãã¯ããgtestã«ããdealã®ãã¹ãã¯ãä¾ãã°ãããªã³ã¼ãã«ãªãã¾ãï¼
TEST(case01,test00) { Account acc; std::queue<int> amounts; // amountã«åå¼é¡ãè¨å® æ£:é å ¥/è² :å¼åº amounts.push(2); amounts.push(-1); amounts.push(3); int expected = amounts.size(); int result = deal(&acc, amounts); EXPECT_EQ(expected, result + amounts.size()); // çµæã®æ¤è¨¼ }
ãã¨ããã§class Accountã¯ä»æ§ã¯æ±ºã¾ã£ã¦ã¯ãããã®ã®ãã¾ã å®è£ ããã¦ãã¾ããããã¨ãå®æãã¦ãã¦ãç¾å®ã®éè¡å£åº§ãæä½ãããã¸ããã®Accountããã¹ãã«ä½¿ãã»ã©ã®åº¦è¸ã¯ããã¾ãããããã¨ã使ããã¨ãã¦ãåå¼ã"ããã¨"æåï¼å¤±æãããã®ã¯å°é£ã§ããããã
ãgmockã使ã£ã¦Accountã®ããªããï¼MockAccountãä½ããAccountã®ä»£å½¹ãåãããããã¨ã«ãã¾ãã
#ifndef ACCOUNT_H_ #define ACCOUNT_H_ class Account { public: virtual bool deposit(int amount) =0; virtual bool withdraw(int amount) =0; }; #endif
ãAccountã®å®è£ ã¯è¦ããªãã®ã§ã¡ã³ãé¢æ°ã¯ãã¹ã¦pure-virtualã§ãã
ããã®AccountããMockAccountãå°åºãã¾ãã
#ifndef MOCKACCOUNT_H_ #define MOCKACCOUNT_H_ #include "Account.h" #include <gmock/gmock.h> class MockAccount : public Account { public: MOCK_METHOD1(deposit, bool(int)); MOCK_METHOD1(withdraw, bool(int)); }; #endif
ããã¯ãï¼MOCK_METHOD#(é¢æ°å, æ»ãå(å¼æ°å...); ã§ãåºåºã¯ã©ã¹ã§å®£è¨ãããã¡ã³ãé¢æ°ãoverrideãã¾ãããã¯ãåæ«å°¾ã®æ°åã¯å¼æ°ã®æ°ãconstã¡ã³ãé¢æ°ã«ã¯MOCK_CONST_METHOD#ãç¨ãã¾ããMockä½ãã¯ããã§ãªã·ãã¤ãç°¡åã§ããï¼ Acountã®ä»£å½¹ã¨ãã¦MockAccountã®åã¡ã³ãé¢æ°ãå¼ã³åºãããã¨ãã«ããã¹ãã±ã¼ã¹ã«å¿ãã¦ã«ç°ãªãæåãä¸ãããã¨ãã§ãã¾ãã
ãããããã«ãããã¼ã«å®è£ ãã¡ãã£ãï¼ãã£ã¨ãã°ã ããã®ï¼ãã¹ã対象ï¼dealãæ¸ãã¦ããã¾ãããããã¤ãgtestã¨gmockã§ãã¹ããã¾ãã
#include "deal.h" // ãã£ã¨ãã°ã ããã® deal int deal(Account* acc, std::queue<int>& amounts) { int count = 0; // æåããåå¼æ° // åå¼ããªããªãã¾ã§ while ( !amounts.empty() ) { // åå¼ãä¸ã¤åãåºã int amount = amounts.front(); amounts.pop(); // åå¼é¡ã®æ£è² ã«å¿ãã¦é å ¥/æåº bool success = (amount > 0) ? acc->deposit(amount) : acc->withdraw(amount); if ( success ) { // æåãããcount-up ++count; } else { break; // 失æãããããã§ä¸æ } } return count; // æåæ°ãè¿ã }