Google Test
| Google Test 主頁:http://code.google.com/p/googletest/ 教程:http://code.google.com/p/googletest/wiki/V1_6_Documentation 斷言 ASSERT_* 一旦失敗立即退出當前函數,EXPECT_* 還能繼續下去。 基礎斷言
數據比較
字符串比較 針對C形式的字符串,即char*或wchar_t*對比測試:
浮點數比較
下面的斷言允許你自己選擇可接受的誤差范圍:
異常斷言
ASSERT_THROW(Foo(5), bar_exception); ? EXPECT_NO_THROW({ ??????? int n = 5; ??????? Bar(&n); ??????? }); 謂語斷言 用戶可以根據需求自定義斷言:
最多支持5個參數 //判斷是否互質 bool MutuallyPrime(int m, int n) { ... } const int a = 3; const int b = 4; const int c = 10; EXPECT_PRED2(MutuallyPrime, a, b); EXPECT_PRED2(MutuallyPrime, b, c); MutuallyPrime(a, b) is true, where ??????? a is 3 ??????? b is 4 MutuallyPrime(b, c) is false, where ??????? b is 4 ??????? c is 10 用戶可以自定義謂語斷言的輸出流:
pred_format采用的是如下函數形式: /** * @brief PredicateFormattern pred_format函數 * * @param expr1 val1的名稱 * @param expr2 val2的名稱 * @param exprn valn的名稱 * @param val1 參數val1 * @param val2 參數val2 * @param valn 參數valn * * @return 返回類型為test::AssertionResult */ testing::AssertionResult PredicateFormattern( ??????? const char* expr1, const char* expr2, ... const char* exprn, ??????? T1 val1, T2 val2, ... Tn valn); test::AssertionResult的返回類型有兩個值如下: namespace testing { ??????? //成功 ??????? AssertionResult AssertionSuccess(); ??????? //失敗 ??????? AssertionResult AssertionFailure(const Message& msg); } 作為例子,我們來改善前面使用EXPECT_PRED2()的那個例子里的失敗信息: //求最小公約數 int SmallestPrimeCommonDivisor(int m, int n) { ... } ? //自己聲明pre_format()的例子 testing::AssertionResult AssertMutuallyPrime(const char* m_expr, const char* n_expr, int m, int n) //前兩個是參數名稱:a,b 后面兩個是a和b的傳入值 { ??????? //判斷互質 ??????? if (MutuallyPrime(m, n)) ?????????????? return testing::AssertionSuccess();//返回成功 ??????? //定義了一個testing::Message來打印出錯信息 ??????? testing::Message msg; ??????? //自己定義的出錯格式 ??????? msg << m_expr << " and " << n_expr << " (" << m << " and " << n ?????????????? << ") are not mutually prime, " << "as they have a common divisor " ?????????????? << SmallestPrimeCommonDivisor(m, n); ??????? return testing::AssertionFailure(msg);//返回失敗,并傳入出錯信息作為參數 } ? //調用方法 EXPECT_PRED_FORMAT2(AssertMutuallyPrime, b, c); 打印結果: b and c (4 and 10) are not mutually prime, as they have a common divisor 2 死亡測試 任何檢查程序是否按預期退出的測試:
statement是一個可能造成進程死亡的程序段。 ·???????? 如: bool f(), true 或 a==b Google Test自帶了兩種判斷進程結束的斷言函數,返回值為bool,只接受一個int參數: testing::ExitedWithCode(exit_code); testing::KilledBySignal(signal_number); TEST(MyDeathTest, Foo) { ??????? // This death test uses a compound statement. ??????? ASSERT_DEATH({ int n = 5; Foo(&n); }, "Error on line .* of Foo()"); } TEST(MyDeathTest, NormalExit) { ??????? //testing::ExitedWithCode(exit_code)返回碼必須一致才算測試成功 ??????? EXPECT_EXIT(NormalExit(), testing::ExitedWithCode(0), "Success"); } TEST(MyDeathTest, KillMyself) { ??????? //testing::KilledBySignal(signal_number)殺死進程的信號必須一致才算測試成功 ??????? EXPECT_EXIT(KillMyself(), testing::KilledBySignal(SIGKILL), "Sending myself unblockable signal"); } 檢驗項目: ·???????? Foo(5) 使進程死亡并得到指定的信息。 ·???????? NormalExit() 使進程打印”Success” 到stderr并且退出碼為0。 ·???????? KillMyself() 使用信號 SIGKILL 殺死進程。 Death斷言只適用于Linux Windows的HRESULT斷言 這些斷言用于測試HRESULT成功或失敗:
HRESULT斷言只適用于windows 測試框架 測試用例main函數,頭文件只要包含gtest/gtest.h即可: gtest_main.cc #include <iostream> ? #include "gtest/gtest.h" ? GTEST_API_ int main(int argc, char **argv) { ? std::cout << "Running main() from gtest_main.cc\n"; ? ? testing::InitGoogleTest(&argc, argv); ? return RUN_ALL_TESTS(); } TEST 簡單測試用例 TEST(test_case_name, test_name){} 第一個參數是測試用例名稱,第二個參數是一個該用例中的測試名稱。 #include "gtest/gtest.h" ? TEST(TestFactorial, ZeroInput) { ??????? EXPECT_EQ(1, Factorial(0)); } ? TEST(TestFactorial, OtherInput) { ??????? EXPECT_EQ(1, Factorial(1)); ??????? EXPECT_EQ(2, Factorial(2)); ??????? EXPECT_EQ(6, Factorial(3)); ??????? EXPECT_EQ(40320, Factorial(8)); } TEST_F TEST_F(test_fixture, test_name){} 第一個參數測試夾具名稱,第二個參數測試該測試夾具中的一個測試名稱。 #include "gtest/gtest.h" ? // 用于測試Foo類的測試夾具,繼承類testing::Test class FooTest : public ::testing::Test { ??????? protected: ?????????????? // 在該測試用例的第一個測試開始前調用 ?????????????? static void SetUpTestCase() { ?????????????????????? shared_resource_ = new ...; ?????????????? } ? ?????????????? // 在該測試用力的最后一個測試結束后調用 ?????????????? static void TearDownTestCase() { ?????????????????????? delete shared_resource_; ?????????????????????? shared_resource_ = NULL; ??????? ??????? } ? ?????????????? // 如果構造和析構還不能滿足你的設置、清理工作 ?????????????? // 你還可以在下面兩個函數里做這些 ?????????????? virtual void SetUp() { ... } ?????????????? virtual void TearDown() { ... } ? ?????????????? static T* shared_resource_; }; ? T* FooTest::shared_resource_ = NULL; ? TEST_F(FooTest, Test1) { ??????? ... you can refer to shared_resource here ... } TEST_F(FooTest, Test2) { ??????? ... you can refer to shared_resource here ... } TEST_P 值參數測試: class FooTest : public ::testing::TestWithParam<const char*> { ??????? // 通過調用函數GetParam()來獲取模板類型的值 ??????? // 如:該類const char*模版類型的值 ??????? // 具體取值見下面的INSTANTIATE_TEST_CASE_P() }; ? //如果想對已有的測試夾具加上值參數測試如下: class BaseTest : public ::testing::Test { ??????? ... }; class BarTest : public BaseTest, ?????????????? public ::testing::WithParamInterface<const char*> { ?????????????????????? ... }; TEST_P(CaseName, TestName){} 第一個參數測試夾具名稱,第二個參數測試該測試夾具中的一個測試名稱。 TEST_P(FooTest, DoesBlah) { ??????? // 可以直接訪問GetParam()函數來獲取值參數 ??????? // 如:該類const char*模版類型的值 ??????? // 具體取值見下面的INSTANTIATE_TEST_CASE_P() ??????? EXPECT_TRUE(foo.Blah(GetParam())); ??????? ... } ? TEST_P(FooTest, HasBlahBlah) { ??????? ... } INSTANTIATE_TEST_CASE_P(InstantiationName, ?????????????? CaseName, ?????????????? ValuesPred); 第一個參數實例化名稱
Combine也可以通過定義宏使其生效: INSTANTIATE_TEST_CASE_P(InstantiationName, ?????????????? FooTest, ?????????????? ::testing::Values("meeny", "miny", "moe")); // 上面的GetParam()取值為"meeny", "miny", "moe"三個進行測試。 ? const char* pets[] = {"cat", "dog"}; INSTANTIATE_TEST_CASE_P(AnotherInstantiationName, FooTest, ?????????????? ::testing::ValuesIn(pets)); // GetParam()從數組中進行取值 Combine詳細用法 TYPED_TEST 模版類型測試: //模版類型測試夾具 template <typename T> class FooTest : public ::testing::Test { ??????? public: ?????????????? ... ?????????????? typedef std::list<T> List; ?????????????? static T shared_; ?????????????? T value_; }; TYPED_TEST_CASE(CaseName, Types){} 第一個參數夾具即測試用例名稱,第二個參數Types<> //該測試模塊是否可用 #if GTEST_HAS_TYPED_TEST ? typedef ::testing::Types<char, int, unsigned int> MyTypes; //初始化所有模版類型,必須要有的 //相當于測試了FooTest<char>,FooTest<int>和FooTest<unsigned int>三個類 TYPED_TEST_CASE(FooTest, MyTypes); TYPED_TEST(CaseName, TestName){} 第一個參數夾具即測試用例名稱,第二個參數該用例中的某一個測試名稱 TYPED_TEST(FooTest, DoesBlah) { ? ??????? //通過TypeParam來獲得模版類型 ??????? TypeParam n = this->value_; ? ??????? n += TestFixture::shared_; ? ??????? //型別重命名 ??????? typename TestFixture::List values; ??????? values.push_back(n); ??????? ... } ? #endif? // GTEST_HAS_TYPED_TEST TYPED_TEST_P 模版類型參數測試: template <typename T> class FooTest : public ::testing::Test { ??????? ... }; TYPED_TEST_CASE_P(FooTest); 只有一個參數測試夾具名稱 TYPED_TEST_P(CaseName, TestName){} 第一個參數夾具即測試用例名稱,第二個參數該用例中的某一個測試名稱 TYPED_TEST_P(FooTest, DoesBlah) { ??????? //同上也是通過TypeParam來獲得模版類型 ??????? TypeParam n = 0; ??????? ... } ? TYPED_TEST_P(FooTest, HasPropertyA) { ... } // 在實例化之前,告訴測試系統需要注冊的用例和實際測試 // REGISTER_TYPED_TEST_CASE_P(CaseName, TestName1, TestName2, ...) REGISTER_TYPED_TEST_CASE_P(FooTest, ?????????????????????????????? DoesBlah, HasPropertyA); // 實力化測試的模板類型 typedef ::testing::Types<char, int, unsigned int> MyTypes; INSTANTIATE_TYPED_TEST_CASE_P(InstantiateName, FooTest, MyTypes); ? //如果只有一個類型的化也可以直接填 INSTANTIATE_TYPED_TEST_CASE_P(My, FooTest, int); 個人感覺和TYPED_TEST測試作用很相似,只不過一個實例化類型在前一個在后。 FRIEND_TEST 友元測試,用來測試類的似有成員: // foo.h #include "gtest/gtest_prod.h" ? // 待測試的類 class Foo { ??????? ... ??????? private: ?????????????? //定義友元測試的用例和測試 ?????????????? FRIEND_TEST(FooTest, BarReturnsZeroOnNull); ?????????????? int Bar(void* x); }; ? // foo_test.cc // 用例和測試名一致 TEST(FooTest, BarReturnsZeroOnNull) { ??????? Foo foo; ??????? // 可以使用私有成員變量了 ??????? EXPECT_EQ(0, foo.Bar(NULL)); } 夾具測試使用FRIEND_TEST的例子: // foo.h namespace my_namespace { ? ??????? class Foo { ?????????????? friend class FooTest; ?????????????? FRIEND_TEST(FooTest, Bar); ?????????????? FRIEND_TEST(FooTest, Baz); ?????????????? ... ?????????????????????? definition of the class Foo ?????????????????????? ... ??????? }; ? }? // namespace my_namespace ? // foo_test.cc namespace my_namespace { ??????? class FooTest : public ::testing::Test { ?????????????? protected: ?????????????????????? ... ??????? }; ? ??????? TEST_F(FooTest, Bar) { ... } ??????? TEST_F(FooTest, Baz) { ... } ? }? // namespace my_namespace Others TestInfo namespace testing { ? ??????? class TestInfo { ?????????????? public: ?????????????????????? // 測試用例名稱 ?????????????????????? const char* test_case_name() const; ? ?????????????????????? // 測試名稱 ?????????????????????? const char* name() const; ? ?????????????????????? // 模板類型名稱,主要用在TYPED_TEST和TYPED_TEST_P中 ?????????????????????? const char* type_param() const; ? ?????????????????????? // 值參數名稱,主要用在TEST_P中 ?????????????????????? const char* value_param() const; ? ??????? }; ? } TEST(CaseName, TestName) { ??????? const ::testing::TestInfo* const test_info = ?????????????? ::testing::UnitTest::GetInstance()->current_test_info(); ??????? printf("We are in test %s of test case %s.\n", ?????????????????????? test_info->name(), test_info->test_case_name()); } ? //打印結果: //We are in test TestName of test case CaseName. TestPartResult 斷言的測試結果: class TestPartResult { ??????? public: ?????????????? // explicit SUCCEED(), FAIL(), or ADD_FAILURE()). ?????????????? enum Type { ?????????????????????? kSuccess,????????? // 成功 ?????????????????????? kNonFatalFailure,? // 非致命斷言失敗,但是測試可以繼續EXPECT_*斷言失敗時返回結果 ?????????????????????? kFatalFailure????? // 致命斷言失敗,但是測試無法繼續ASSERT_*斷言失敗時返回結果 ?????????????? }; ?????????????? // 返回測試斷言結果 ?????????????? Type type() const; ? ?????????????? // 斷言所在文件名 ?????????????? const char* file_name() const; ? ?????????????? // 斷言所在行號 ?????????????? int line_number() const; ? ?????????????? // 失敗信息概要 ?????????????? const char* summary() const; ? ?????????????? // 這部分測試關聯的消息 ?????????????? const char* message() const; ? ?????????????? // 返回測試是否成功,true表示成功 ?????????????? bool passed() const { return type_ == kSuccess; } ? ?????????????? // 返回測試是否失敗,true表示失敗 ?????????????? bool failed() const { return type_ != kSuccess; } ? ?????????????? // 返回測試是否為非致命斷言失敗 ?????????????? bool nonfatally_failed() const { return type_ == kNonFatalFailure; } ? ?????????????? // 返回測試是否為致命斷言失敗 ?????????????? bool fatally_failed() const { return type_ == kFatalFailure; } }; // 都支持流輸出 TEST(CaseName, TestName) { ??????? // 產生一個斷言成功的TestPartResult ??????? SUCCEED()<<"Something..."; ? ??????? // 產生一個非致命斷言失敗的TestPartResult ??????? ADD_FAILURE()<<"Something..."; ? ??????? // 產生一個致命斷言失敗的TestPartResult ??????? FAIL()<<"Something..."; } Event Listeners 事件監聽: class EmptyTestEventListener : public TestEventListener { ??????? public: ?????????????? // Listener的被調用順序一般會和下面順序相差不多 ? ? ?????????????? // 測試程序啟動時候調用,即RUN_ALL_TESTS()剛開始運行時候調用 ?????????????? virtual void OnTestProgramStart(const UnitTest& /*unit_test*/) {} ? ?????????????? // 根據repeat次數多次調用,每次重復開始時調用,第二個參數傳入第幾次重復,從0開始。 ?????????????? virtual void OnTestIterationStart(const UnitTest& /*unit_test*/, ?????????????????????????????? int /*iteration*/) {} ? ? ?????????????? // SetUp()調用開始前調用 ?????????????? virtual void OnEnvironmentsSetUpStart(const UnitTest& /*unit_test*/) {} ? ?????????????? // SetUp()調用結束時調用 ?????????????? virtual void OnEnvironmentsSetUpEnd(const UnitTest& /*unit_test*/) {} ? ? ?????????????? // 測試用例開始時調用 ?????????????? virtual void OnTestCaseStart(const TestCase& /*test_case*/) {} ? ?????????????? // 測試用例中的單個測試開始時調用 ?????????????? virtual void OnTestStart(const TestInfo& /*test_info*/) {} ? ?????????????? // 每個斷言結束后調用,TestPartResult參數傳入斷言的結果,詳見上節 ?????????????? virtual void OnTestPartResult(const TestPartResult& /*test_part_result*/) {} ? ?????????????? // 測試用例中的單個測試結束時調用 ?????????????? virtual void OnTestEnd(const TestInfo& /*test_info*/) {} ? ?????????????? // 測試用例結束時調用 ?????????????? virtual void OnTestCaseEnd(const TestCase& /*test_case*/) {} ? ? ?????????????? // TearDown()調用開始前調用 ?????????????? virtual void OnEnvironmentsTearDownStart(const UnitTest& /*unit_test*/) {} ? ?????????????? // TearDown()調用結束后調用 ?????????????? virtual void OnEnvironmentsTearDownEnd(const UnitTest& /*unit_test*/) {} ? ? ?????????????? // 根據repeat次數多次調用,每次重復結束時調用,第二個參數傳入第幾次重復,從0開始。 ?????????????? virtual void OnTestIterationEnd(const UnitTest& /*unit_test*/, ?????????????????????????????? int /*iteration*/) {} ? ?????????????? // 測試程序結束時候調用,即RUN_ALL_TESTS()剛結束運行時候調用 ?????????????? virtual void OnTestProgramEnd(const UnitTest& /*unit_test*/) {} }; 詳細例子 運行選項 運行時可以通過–help, -h, -?或/?,來打印運行選項的幫助列表,所有的參數都是以兩個-開頭。 //--gest_print_time int main(int argc, char** argv) { ??????? // 關閉顯示運行時間 ??????? // --gest_print_time ??????? ::testing::GTEST_FLAG(print_time) = false; ? ??????? // --gest_list_tests ??????? ::testing::GTEST_FLAG(list_tests) = true; ? ??????? // 這句代碼將運行參數傳入Google Test中 ??????? ::testing::InitGoogleTest(&argc, argv); ? ??????? return RUN_ALL_TESTS(); } gtest_list_tests 不進行測試只顯示所有測試列表: TestCase1. ??????? TestName1 ??????? TestName2 TestCase2. ??????? TestName gtest_filter 對測試進行過濾,只運行指定的測試: * 代表任意數量任意字符 ? 代表任意單個字符 : 代表或者的關系 - 代表去除該匹配測試 . 代表左邊是測試用例名,右邊是具體測試名稱 例如: ·???????? ./foo_test 無參數,運行所有測試 ·???????? ./foo_test –gtest_filter=* 運用*通配符,也是運行所有測試 ·???????? ./foo_test –gtest_filter=FooTest.* 只運行所有在FooTest測試用例中的測試 ·???????? ./foo_test –gtest_filter=*Null*:*Constructor* 只運行帶有Null或者Constructor字符串的測試 ·???????? ./foo_test –gtest_filter=-*DeathTest.* 運行除了帶有DeathTest字符串的測試用例中的所有測試 ·???????? ./foo_test –gtest_filter=FooTest.*-FooTest.Bar 運行在FooTest測試用例中除了FooTest.Bar的測試 gtest_also_run_disabled_tests 通常運行測試的時候,測試系統會自動禁止DISABLED_*為測試用例或測試名稱的測試運行。 // 默認是不運行的,加上運行選項則運行 TEST(FooTest, DISABLED_DoesAbc) { ... } ? class DISABLED_BarTest : public ::testing::Test { ... }; TEST_F(DISABLED_BarTest, DoesXyz) { ... } gtest_color --gtest_color=(yes|no|auto) ? Enable/disable colored output. The default is auto. gtest_print_time --gtest_print_time=0 ? Don't print the elapsed time of each test. gtest_repeat 對測試進行重復運行,會把當前測試序號傳遞給TestEventListeners的OnTestIterationStart和OnTestIterationEnd第二個參數,詳見Event Listeners:
gtest_shuffle 擾亂重復測試的順序,將當前序號打亂傳給OnTestIterationStart和OnTestIterationEnd,必須要和gtest_repeat選項同時使用。 gtest_random_seed 給gtest_shuffle設置SEED,0-9999之間,0代表取當前系統時間為SEED。 gtest_output 支持xml格式的輸出:
gtest_stream_result_to 定向輸出流到指定服務器: --gtest_stream_result_to=HOST:PORT ? HOST服務器IP或域名,PORT服務器端口 gtest_death_test_style --gtest_death_test_style=(fast|threadsafe) ? Set the default death test style. gtest_break_on_failure --gtest_break_on_failure ? Turn assertion failures into debugger break-points. 非常利于調試 gtest_throw_on_failure --gtest_throw_on_failure ? Turn assertion failures into C++ exceptions. gtest_catch_exceptions --gtest_catch_exceptions=0 ? Do not report exceptions as test failures. Instead, allow them ? to crash the program or throw a pop-up (on Windows). 1) ValuesIn(const T (&array)[N]) //數組 ValuesIn(const Container& container) //STL容器 ValuesIn(Iterator begin, Iterator end) //迭代器 |
?
超強干貨來襲 云風專訪:近40年碼齡,通宵達旦的技術人生總結
以上是生活随笔為你收集整理的Google Test的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 深入理解gtest C/C++单元测试经
- 下一篇: C++不懂的问题