因為閱讀chromium的需要,想簡單學習一下gtest的使用,因為通過chromium的unit_test是瞭解webkit chromium port的一個途徑。其實gtest的相關文章比較多,本文後面的參考文獻列出了一些代表性的文章,是學習使用gtest的有價值的資料。
首先看一下邏輯概念:
一個test_program可以包含多個test_case,而一個test_case又可以包含多個test,一個test_program是指一個包含main函數的link unit,也就是一個test_program只能包含一個main函數,和多個test檔案,這些test檔案中包含多個test_case,而一個test_case又包含多個test。如所示:
gtest使用一些宏來判斷是否被測試的單元得到期望的結果,宏基本上分為ASSERT_*和EXPECT_*,不同之處是ASSERT_*失敗會終止本test的繼續執行,而EXPECT_*宏是可以繼續執行本test的。比較string是否是空ASSERT_STREQ(NULL, the_string)
如果多個test使用相同的資料,可以使用一個類來共用這些需要共用的資料,這些共用的資料是類的成員變數,這種機制[1]中叫做fixture,fixture擁有SetUp和TearDown函數,用於初始化和析構對象,每個Test執行前都會調用SetUp和TearDown,代碼中測試了這種情況。如果使用fixture,那麼將使用TEST_F宏替代TEST宏,同時test_case的名字要是fixture類的名字(開始時這個地方犯了錯誤)。
一個link unit的test program擁有一個main函數,main函數的編寫通常如下:
int main(int argc, char **argv) { ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS();}
其中RUN_ALL_TEST()函數將運行一個link
unit中全部的tests(RUN_ALL_TESTS() runs all tests in your link unit ),需要注意的一點是main函數一定要返回RUN_ALL_TESTS的傳回值,否則會出錯,即return
RUN_ALL_TESTS(),而且RUN_ALL_TESTS()只能被調用1次,否則會引起線程問題。
下面看些具體的例子,假設我有四個檔案:my_test.cc、my_test1.cc、my_test2.cc、my_class.h
my_test.cc
#include <gtest/gtest.h>TEST(MyTestCase, FirstTest) { EXPECT_EQ(2,2);}TEST(MyTestCase, SecondTest) { EXPECT_EQ(2,2);}int main(int argc, char **argv) { ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS();}
my_test1.cc
#include <gtest/gtest.h>TEST(MyTestCase, ThirdTest) { ASSERT_EQ(3,3) << "3 is not equal to 4"; char* p = NULL; ASSERT_STREQ(NULL, p);}TEST(YourTestCase, FirstTest) { EXPECT_EQ(3,3);}
my_test2.cc
#include <gtest/gtest.h>#include "my_class.h"class MyClassTest : public ::testing::Test { public: virtual void SetUp() { my_class_ = new MyClass(10); } virtual void TearDown() { delete my_class_; } MyClass* my_class_;};TEST_F(MyClassTest, FirstTest) { EXPECT_EQ(10, my_class_->GetX()); my_class_->SetX(2);}TEST_F(MyClassTest, SecondTest) { EXPECT_EQ(10, my_class_->GetX()); my_class_->SetX(2);}
my_class.h
#include <stdio.h>class MyClass { public: MyClass(int x) : x_(x) {} void SetX(int x) { x_ = x; } int GetX() const { return x_; } private: int x_;};
編譯命令如下:
g++ my_test.cc my_test1.cc my_test2.cc -lgtest -lpthread
運行結果
[==========] Running 6 tests from 3 test cases.[----------] Global test environment set-up.[----------] 2 tests from MyClassTest[ RUN ] MyClassTest.FirstTest[ OK ] MyClassTest.FirstTest (0 ms)[ RUN ] MyClassTest.SecondTest[ OK ] MyClassTest.SecondTest (0 ms)[----------] 2 tests from MyClassTest (0 ms total)[----------] 3 tests from MyTestCase[ RUN ] MyTestCase.ThirdTest[ OK ] MyTestCase.ThirdTest (0 ms)[ RUN ] MyTestCase.FirstTest[ OK ] MyTestCase.FirstTest (0 ms)[ RUN ] MyTestCase.SecondTest[ OK ] MyTestCase.SecondTest (0 ms)[----------] 3 tests from MyTestCase (0 ms total)[----------] 1 test from YourTestCase[ RUN ] YourTestCase.FirstTest[ OK ] YourTestCase.FirstTest (0 ms)[----------] 1 test from YourTestCase (0 ms total)[----------] Global test environment tear-down[==========] 6 tests from 3 test cases ran. (0 ms total)[ PASSED ] 6 tests.
其中參考文獻[1]介紹最基礎的gtest的使用,參考文獻[4]給出了一些gtest使用的舉例,參考文獻[5]給出了更多的gtest的使用方法(包括:類型測試、參數測試等等)
參考文獻:
[1]http://code.google.com/p/googletest/wiki/Primer
[2]https://docs.google.com/present/view?id=dfsbxvm5_0f5s4pvf9
[3]http://www.cnblogs.com/coderzh/archive/2009/04/06/1426755.html
[4]http://code.google.com/p/googletest/wiki/Samples
[5]http://code.google.com/p/googletest/wiki/AdvancedGuide