外部依賴項:
liggtest.a libgtest_main.a 相關頭文件
Main函數寫法參考:
int main(int argc,char* argv[])
{
//testing::GTEST_FLAG(output) = "xml:"; //生成xml結果文件
testing::InitGoogleTest(&argc,argv); //初始化
if( RUN_ALL_TESTS()) //跑單元測試
return 0;
}
1.斷言的使用
1)ASSERT_* 斷言
ASSERT_*系列斷言,當檢查點失敗時,退出當前函數
例如:有如下兩個測試用例:
TEST(unit,assert_t_1)
{
ASSERT_EQ(4,Add(1,2));
ASSERT_EQ(3,Add(1,2));
}
TEST(unit,assert_t_2)
{
ASSERT_EQ(4,Add(1,3));
}
輸出結果:
main startinit[==========] Running 2 tests from 1 test suite.
[----------] Global test environment set-up.
[----------] 2 tests from unit
[ RUN ] unit.assert_t_1
unittest.cpp:5: Failure
Expected equality of these values:
4
Add(1,2)
Which is: 3
[ FAILED ] unit.assert_t_1 (0 ms)
[ RUN ] unit.assert_t_2
[ OK ] unit.assert_t_2 (0 ms)
[----------] 2 tests from unit (0 ms total)
[----------] Global test environment tear-down
[==========] 2 tests from 1 test suite ran. (0 ms total)
[ PASSED ] 1 test.
[ FAILED ] 1 test, listed below:
[ FAILED ] unit.assert_t_1
分析:
上面實際上只跑了兩個用例,當 assert_t_1 測試第一個測試點測試失敗時,整個函數都退出,轉向執行第二個函數。
2)EXPECT_* 斷言
EXPECT_* 斷言當檢查點失敗時,會繼續往下執行
例如:如下倆個測試用例:
TEST(unitqxcept,except_t_1)
{
std::cout<<"first point\n";
EXPECT_EQ(4,Add(1,2));
std::cout<<"second point\n";
EXPECT_EQ(3,Add(1,2));
}
TEST(unitqxcept,except_t_2)
{
std::cout<<"third point\n";
EXPECT_EQ(4,Add(1,3));
}
測試結果:
main startinitNote: Google Test filter = unitqxcept.*
[==========] Running 2 tests from 1 test suite.
[----------] Global test environment set-up.
[----------] 2 tests from unitqxcept
[ RUN ] unitqxcept.except_t_1
first point
unittest.cpp:19: Failure
Expected equality of these values:
4
Add(1,2)
Which is: 3
second point
[ FAILED ] unitqxcept.except_t_1 (0 ms)
[ RUN ] unitqxcept.except_t_2
third point
[ OK ] unitqxcept.except_t_2 (0 ms)
[----------] 2 tests from unitqxcept (0 ms total)
[----------] Global test environment tear-down
[==========] 2 tests from 1 test suite ran. (1 ms total)
[ PASSED ] 1 test.
[ FAILED ] 1 test, listed below:
[ FAILED ] unitqxcept.except_t_1
分析:在第一個測試點測試失敗後,函數沒有退出,而是繼續第二個測試點
總結:
常見的斷言有:
布爾值檢查: *_TRUE *_FALSE
數值型檢查: *_EQ 等於 *_NE 不等於 小於 *_LT *_LE 小於等於 *_GT 大於 *_GE 大於等於
字符串檢查: *_STREQ 等於 *_STRNQ 不等於 *_STRCASEEQ 忽略大小寫,兩個子串相等 *_STRCASEEQ 忽略大小寫,兩個子串不相等
2.事件機制(Test Fixures)
gtest的事件機制,方便在gtest的測試用例之前或之後做一些操作。
1)全局事件
全局事件用於在所有案例的前後執行某種操作
測試用例:
class TestEnvironment : public testing::Environment
{
public:
virtual void SetUp()
{
std::cout<<"test environment setup"<<std::endl;
}
virtual void TearDown()
{
std::cout<<"test environment TearDown"<<std::endl;
}
};
定義一個繼承自testing::Environment的類,在main函數中添加語句
testing::AddGlobalTestEnvironment(new TestEnvironment);
測試結果:
[----------] Global test environment set-up.
test environment setup
[----------] 1 test from unitassert
[ RUN ] unitassert.assert_t_1
unittest.cpp:6: Failure
Expected equality of these values:
4
Add(1,2)
Which is: 3
[ FAILED ] unitassert.assert_t_1 (0 ms)
[----------] 1 test from unitassert (0 ms total)
[----------] Global test environment tear-down
test environment TearDown
分析:
由結果看出,在測試用例執行前,執行了 SetUp()打印操作,
在用例執行完成以後,執行TearDown()打印操作。
2)TestSuite事件
在某一個案例第一個案例前,最後一個案例後
測試用例:
class TestSuit : public testing::Test
{
protected:
static void SetUpTestCase()
{
std::cout<<"TestSuit setup"<<std::endl;
}
static void TearDownTestCase()
{
std::cout<<"TestSuit TearDown"<<std::endl;
}
};
TEST_F(TestSuit,except_t_1)
{
EXPECT_EQ(3,Add(1,2));
}
注意,這裏使用了TEST_F宏,宏的第一個參數是類的名字
部分結果:
[ RUN ] unitqxcept.except_t_2
third point
[ OK ] unitqxcept.except_t_2 (0 ms)
[----------] 2 tests from unitqxcept (0 ms total)
[----------] 1 test from TestSuit
TestSuit setup
[ RUN ] TestSuit.except_t_1
[ OK ] TestSuit.except_t_1 (0 ms)
TestSuit TearDown
分析:
如上述結果所示,TestSuit的SetUp只在TestSuit.except_t_1之前執行
TestSuit TearDown的TearDown只在TestSuit.except_t_1之後執行。
3) TestCase事件與TestSuit基本相同,不再贅述
3.參數化
有些被測試函數需要傳入多個不同的參數,爲了避免書寫重複代碼,可以使用值參數化
1)值參數化
測試用例:
class IsPrimeParamTest : public::testing::TestWithParam<int>
{
};
bool IsPrime(int n)
{
if(n<=1)return false;
if(n%2==0)return n==2;
for(int i =3;;i+=2)
{
if(i>n/i)break;
if(n%2 ==0)return false;
}
return true;
}
INSTANTIATE_TEST_CASE_P(TrueReturn,IsPrimeParamTest,testing::Values(3,5,11,23,17)); //設定參數範圍
TEST_P(IsPrimeParamTest,HandleTrueReturn)
{
int n = GetParam();
EXPECT_TRUE(IsPrime(n));
}
測試結果:
[----------] 1 test from TestSuit (0 ms total)
[----------] 5 tests from TrueReturn/IsPrimeParamTest
[ RUN ] TrueReturn/IsPrimeParamTest.HandleTrueReturn/0
[ OK ] TrueReturn/IsPrimeParamTest.HandleTrueReturn/0 (0 ms)
[ RUN ] TrueReturn/IsPrimeParamTest.HandleTrueReturn/1
[ OK ] TrueReturn/IsPrimeParamTest.HandleTrueReturn/1 (0 ms)
[ RUN ] TrueReturn/IsPrimeParamTest.HandleTrueReturn/2
[ OK ] TrueReturn/IsPrimeParamTest.HandleTrueReturn/2 (0 ms)
[ RUN ] TrueReturn/IsPrimeParamTest.HandleTrueReturn/3
[ OK ] TrueReturn/IsPrimeParamTest.HandleTrueReturn/3 (0 ms)
[ RUN ] TrueReturn/IsPrimeParamTest.HandleTrueReturn/4
[ OK ] TrueReturn/IsPrimeParamTest.HandleTrueReturn/4 (0 ms)
[----------] 5 tests from TrueReturn/IsPrimeParamTest (0 ms total)
分析:
如上述結果所示,TEST_P(IsPrimeParamTest,HandleTrueReturn)總共跑了5次測試用例
總結:
參數生成器函數:
Range(begin,end[,step]),範圍在begin-end之間,步長爲step,不包括end
Values(v1,v2,....,vN) v1,v2到vN的值
ValuesIn(container)and ValuesIn(begin,end) 從一個數組或容器裏面取值
Bool() 取false和true兩個值
Combine(g1,g2,....,gN) 從g1到gN取出數個值組成元組tuple (不太明白)
2)類型參數化
4.死亡測試
gtest的死亡測試用於在安全的環境下執行奔潰的測試案例
1) *_DEATH 用例因給定的錯誤而崩潰
測試用例:
void Foo()
{
int *pInt = 0;
*pInt = 42;
}
TEST(FooDeathTest,Demo)
{
EXPECT_DEATH(Foo(),"");
}
測試結果:
[==========] Running 1 test from 1 test suite.
[----------] Global test environment set-up.
[----------] 1 test from FooDeathTest
[ RUN ] FooDeathTest.Demo
[ OK ] FooDeathTest.Demo (56 ms)
[----------] 1 test from FooDeathTest (56 ms total)
[----------] Global test environment tear-down
[==========] 1 test from 1 test suite ran. (56 ms total)
[ PASSED ] 1 test.
分析:
Foo()觸發了一個錯誤,測試通過
2)*_EXIT
用例因爲錯誤退出,錯誤碼與謂詞匹配
測試用例:
TEST(ExitDeathTest,Demo)
{
EXPECT_EXIT(_exit(1),testing::ExitedWithCode(1),"");
}
測試結果:
[----------] 1 test from ExitDeathTest
[ RUN ] ExitDeathTest.Demo
[ OK ] ExitDeathTest.Demo (18 ms)
[----------] 1 test from ExitDeathTest (18 ms total)
分析:
推遲的錯誤碼和謂詞匹配,測試通過