++ G Test 版本:1.5.0 *1) 如何運行測試*#define RUN_ALL_TESTS()\ (::testing::UnitTest::GetInstance()->Run()) ------------------------ UnitTestImpl::RunAllTests() test_cases_.ForEach(TestCase::RunTestCase) TestCase::RunTestCase static void RunTestCase(TestCase * test_case) { test_case->Run(); } TestCase::Run() test_info_list_->ForEach(internal::TestInfoImpl::RunTest); static void RunTest(TestInfo * test_info) { test_info->impl()->Run();} TestInfoImpl::Run() test = factory_->CreateTest() test->Run(); Test::Run() TestBody(); ------------------------ 1. UnitTest 單例,總管整個測試,包括測試環境資訊,當前執行狀態等等。 2. UnitTestImpl UnitTest內部具體功能的實現者。 3. Test 我們自己編寫的,或通過TEST,TEST_F等宏展開後的Test對象,管理著測試案例的前後事件,具體的執行代碼TestBody。 4. TestCase 測試案例對象,管理著基於TestCase的前後事件,管理內部多個TestInfo。 5. TestInfo 管理著測試案例的基本資料,包括Test對象的建立方法。 6. TestInfoImpl TestInfo內部具體功能的實現者 。 ---------------- *2 )如何產生測試* --------------- TEST(FooTest, Demo) { EXPECT_EQ(1, 1); } --------------- 展開 --------------- class FooTest_Demo_Test : public ::testing::Test { public: FooTest_Demo_Test() {} private: virtual void TestBody(); static ::testing::TestInfo* const test_info_; FooTest_Demo_Test(const FooTest_Demo_Test &); void operator=(const FooTest_Demo_Test &); }; ::testing::TestInfo* const FooTest_Demo_Test ::test_info_ = ::testing::internal::MakeAndRegisterTestInfo( "FooTest", "Demo", "", "", (::testing::internal::GetTestTypeId()), ::testing::Test::SetUpTestCase, ::testing::Test::TearDownTestCase, new ::testing::internal::TestFactoryImpl< FooTest_Demo_Test>); void FooTest_Demo_Test::TestBody() { switch (0) case 0: if (const ::testing::AssertionResult gtest_ar = (::testing::internal:: EqHelper<(sizeof(::testing::internal::IsNullLiteralHelper(1)) == 1)>::Compare("1", "1", 1, 1))) ; else ::testing::internal::AssertHelper( ::testing::TPRT_NONFATAL_FAILURE, ".\\gtest_demo.cpp", 9, gtest_ar.failure_message() ) = ::testing::Message(); } 展開後,我們觀察到: 1. TEST宏展開後,是一個繼承自testing::Test的類。 2. 我們在TEST宏裡面寫的測試代碼,其實是被放到了類的TestBody方法中。 3. 通過靜態變數test_info_,調用MakeAndRegisterTestInfo對測試案例進行註冊。 ++ Test Info 我們看到,上面建立了一個TestInfo對象,然後通過AddTestInfo註冊了這個對象。TestInfo對象到底是一個什麼樣的東西呢? TestInfo對象主要用於包含如下資訊: 1. 測試案例名稱(testcase name) 2. 測試名稱(test name) 3. 該案例是否需要執行 4. 執行案例時,用於建立Test對象的函數指標 5. 測試結果 我們還看到,TestInfo的建構函式中,非常重要的一個參數就是工廠對象,它主要負責在運行測試案例時建立出Test對象。我們看到我們上面的例子的factory為: new ::testing::internal::TestFactoryImpl< FooTest_Demo_Test> 我們明白了,Test對象原來就是TEST宏展開後的那個類的對象(FooTest_Demo_Test),再看看TestFactoryImpl的實現: template <class TestClass> class TestFactoryImpl : public TestFactoryBase { public: virtual Test* CreateTest() { return new TestClass; } }; ++ Test Factory Impl template <class TestClass> class TestFactoryImpl : public TestFactoryBase { public: virtual Test* CreateTest() { return new TestClass; } }; ++ Make And Register Test Info // 建立一個 TestInfo 對象並註冊到 Google Test; // 返回建立的TestInfo對象 // // 參數: // // test_case_name: 測試案例的名稱 // name: 測試的名稱 // test_case_comment: 測試案例的注釋資訊 // comment: 測試的注釋資訊 // fixture_class_id: test fixture類的ID // set_up_tc: 事件函數SetUpTestCases的函數地址 // tear_down_tc: 事件函數TearDownTestCases的函數地址 // factory: 工廠對象,用於建立測試對象(Test) TestInfo* MakeAndRegisterTestInfo( const char* test_case_name, const char* name, const char* test_case_comment, const char* comment, TypeId fixture_class_id, SetUpTestCaseFunc set_up_tc, TearDownTestCaseFunc tear_down_tc, TestFactoryBase* factory) { TestInfo* const test_info = new TestInfo(test_case_name, name, test_case_comment, comment, fixture_class_id, factory); GetUnitTestImpl()->AddTestInfo(set_up_tc, tear_down_tc, test_info); return test_info; } -------------------------- *3)如何使用gtest* ++ How To Use Gtest gtest使用簡介 最近測試過程中使用gtest,簡單易用,是一個非常不錯的單元測試架構,簡單介紹下使用方法,歡迎大家拍磚 一、安裝 官網:http://code.google.com/p/googletest/ 1、下載最新版本:gtest-1.4.0.tar.gz 2、解壓後進入gtest-1.4.0 3、 運行./configure make make install(需要sudo許可權,也可以自己指定安裝的目錄) 4、 進入根目錄,編輯.bashrc,添加庫檔案路徑export LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH (編譯測試程式時可以找到產生的gtest庫檔案) 二、調用 1、編寫測試程式時添加#include <gtest/gtest.h> 2、編譯測試程式時添加以下內容-ldl -lgtest -I/usr/local/include(載入gtest標頭檔) 代碼: #include <iostream> #include <cstdlib> using namespace std; #include <gtest/gtest.h> int Fun(int val) { return val; } //測試案例 TEST(Test, TestFun) { //檢查函數的傳回值是否與給定的值相等 EXPECT_EQ(10, Fun(10)); EXPECT_EQ(9, Fun(10)); } int main(int argc, char* argv[]) { //初始化 testing::InitGoogleTest(&argc, argv); //運行所有的測試案例 RUN_ALL_TESTS(); system("pause"); return 0; } 宏與事件 斷言宏可以理解分為兩類,一類是ASSERT,另外一類是EXPECT系列。當檢查點失敗的時候,ASSERT系列的宏會退出當前函數,EXPECT系列的斷言會繼續往下執行。 Gtest中定義了多種宏來針對不同的需求,有針對布爾類型的宏,有針對數實值型別進行邏輯檢查的宏,針對字串的宏。針對異常檢查的宏,還有一些針對特殊情況下使用的宏。 宏的主要作用就是檢查所有測試的函數是否按照我們的預期進行了工作。 事件機制:使我們能在案例之前和之後做一些操作。事件一般分為三種類型: 1. 全域的,所有案例執行前後。 2. TestSuit層級的,在某一批案例中的第一個案例前,最後一個案例執行後。 3. TestCase層級的,每一個TestCase前後。 事件的實現 4. 全域事件 寫一個類,繼承test::Environment類,實現裡面的setup和teardown。Setup在所有案例執行前執行,teardown在所有案例執行後執行。 5. TestSuit 寫一個類繼承testing::Test,然後實現兩個靜態方法,setuptestcase,它在第一個testcase之前執行。Teardowntestcase在最後一個testcase之後執行。然後再編寫測試案例的時候,需要使用TEST_F宏,第一個參數使用,我們衍生類別的名字。 6. TestCase 寫一個類,繼承testing::Test,然後重寫方法setup和teardown。Setup方法在每個testcase之前執行,teardown方法在每個testcase之後執行。編寫測試案例的時候同樣需要使用TEST_F宏。 7. 四、程式部分測試結果 Gtest對每個失敗的case給出預期值與實際值的差別以及失敗case的名稱 五、gtest斷言 布爾值檢查 Fatal assertion Nonfatal assertion Verifies ASSERT_TRUE(condition); EXPECT_TRUE(condition); conditionis true ASSERT_FALSE(condition); EXPECT_FALSE(condition); conditionis false 數值型資料檢查 Fatal assertion Nonfatal assertion Verifies ASSERT_EQ(expected, actual); EXPECT_EQ(expected, actual); expected == actual ASSERT_NE(val1, val2); EXPECT_NE(val1, val2); val1 != val2 ASSERT_LT(val1, val2); EXPECT_LT(val1, val2); val1 < val2 ASSERT_LE(val1, val2); EXPECT_LE(val1, val2); val1 <= val2 ASSERT_GT(val1, val2); EXPECT_GT(val1, val2); val1 > val2 ASSERT_GE(val1, val2); EXPECT_GE(val1, val2); val1 >= val2 字串檢查 Fatal assertion Nonfatal assertion Verifies ASSERT_STREQ(expected_str, actual_str); EXPECT_STREQ(expected_str, actual_str); the two C strings have the same content ASSERT_STRNE(str1, str2); EXPECT_STRNE(str1, str2); the two C strings have different content ASSERT_STRCASEEQ(expected_str, actual_str); EXPECT_STRCASEEQ(expected_str, actual_str); the two C strings have the same content, ignoring case ASSERT_STRCASENE(str1, str2); EXPECT_STRCASENE(str1, str2); the two C strings have different content, ignoring case 更多詳細資料請參看 官方文檔:http://code.google.com/p/googletest/wiki/GoogleTestPrimer 推薦文檔:http://www.cnblogs.com/coderzh/archive/2009/03/31/1426758.html |