單元測試
項(xiàng)目管理和技術(shù)管理中做單元測試,衡量一個(gè)軟件是否正常的標(biāo)準(zhǔn),良好的單元測試以及足夠多的覆蓋率,至少保證關(guān)鍵功能,關(guān)鍵業(yè)務(wù)的覆蓋率接近100%。
gtest是谷歌公司發(fā)布的一個(gè)跨平臺(tái)(Linux、Mac OS、Windows等)的C++單元測試框架,它提供了豐富的斷言、致命和非致命判斷、參數(shù)化、死亡測試等等。
-
兩種斷言:
- ASSERT_*:當(dāng)斷言失敗時(shí),產(chǎn)生致命錯(cuò)誤、并終止當(dāng)前函數(shù)。
- EXPECT_*:當(dāng)斷言失敗時(shí),產(chǎn)生非致命錯(cuò)誤,并且不會(huì)終止當(dāng)前函數(shù)。
- 通常都會(huì)用EXPECT_*,因?yàn)槟茉谝淮螠y試中測試出更多的失敗情況。
- 如果要在出現(xiàn)失敗測試時(shí)立即終止程序,則要選擇ASSERT_*
- ==注意:==因?yàn)锳SSERT_*會(huì)在失敗時(shí)立即終止函數(shù),那么就可能跳過后面程序中進(jìn)行清理工作的代碼,可能會(huì)產(chǎn)生內(nèi)存泄露。
測試stack
main函數(shù)在gtest_main.cc中,可以把這個(gè)main函數(shù)復(fù)制到你的代碼里面,你將擁有它的控制權(quán)。
GTEST_API_ int main(int argc, char **argv) {
std::cout << "Running main() from gtest_main.cc\n";
testing::InitGoogleTest(&argc, argv);//解析命令行中的GoogleTest參數(shù),它允許用戶通過多樣的命令行參數(shù)來控制測試程序的行為(即定制命令行參數(shù)的行為)
return RUN_ALL_TESTS();//將會(huì)搜索不同的Test Case和不同的源文件中所有已經(jīng)存在測試案例,然后運(yùn)行它們,所有Test都成功時(shí)返回1,否則返回0。
}
-
非致命斷言,即使宏判斷失敗,程序仍然會(huì)順序執(zhí)行后面的代碼
每一個(gè)測試實(shí)例都必須初初始化每一個(gè)對(duì)象
==TEST()宏==的第一個(gè)參數(shù)是Test Case的名稱,第二個(gè)參數(shù)是隸屬于第一個(gè)Test Case參數(shù)的Test的名稱。GoogleTest根據(jù)Test Case對(duì)測試結(jié)果進(jìn)行分組,所以一些相關(guān)的Test應(yīng)該放在同一個(gè)Test Case中。
#include "gtest/gtest.h" #include "MyStack.h" //測試實(shí)例1 TEST(testStack, simpletest) { MyStack st; st.push(4); EXPECT_EQ(4, st.pop());//使用Google Test宏進(jìn)行測試(非致命斷言) } //測試實(shí)例2 TEST(testStack, testAll) { MyStack st; st.push(9); st.push(28); int val = st.pop(); EXPECT_EQ(28, val);//28等于val則測試通過(非致命斷言) EXPECT_NE(0,val);//0不等于val則測試通過(非致命斷言) EXPECT_GT(29, val);//29大于val則測試通過(非致命斷言) EXPECT_GE(29, val);//29大于等于val則測試通過(非致命斷言) EXPECT_TRUE(val == 28) << "val is not equal to 28";//val == 28結(jié)果為false,輸出后面日志(非致命斷言) }
-
致命斷言,如果斷言失敗,當(dāng)前函數(shù)剩下來的代碼將會(huì)被跳過
TEST(testStack, testAll) { MyStack st; st.push(9); st.push(28); int val = st.pop(); ASSERT_EQ(28, val);//28等于val則測試通過(致命斷言) ASSERT_NE(0,val);//0不等于val則測試通過(致命斷言) ASSERT_GT(29, val);//29大于val則測試通過(致命斷言) ASSERT_TRUE(val == 28) << "val is not equal to 28";//val == 28結(jié)果為false,輸出后面日志(致命斷言) }
-
字符串?dāng)嘌?/strong>
TEST(testStack, testAll) { MyStack st; st.push(9); st.push(28); int val = st.pop(); EXPECT_EQ("9", st.toString().c_str());//字符串?dāng)嘌?}
-
浮點(diǎn)數(shù)斷言
TEST(testStack, testAll) { MyStack st; st.push(9); st.push(28); int val = st.pop(); EXPECT_FLOAT_EQ(7.0, ((float)val)/4); EXPECT_DOUBLE_EQ(7.0, ((double)val)/4); }
-
測試裝置(Test Fixtures)
假如我們有非常多的測試實(shí)例,不想重復(fù)初始化
TEST_F()宏,我們想讓多個(gè)Test使用同一套數(shù)據(jù)配置時(shí),就需要用到測試裝置,創(chuàng)建測試裝置的具體方法如下:
- 派生一個(gè)繼承 ::testing::Test 的類,并將該類中的一些內(nèi)容聲明為 protected 類型,以便在子類中進(jìn)行訪問;
- 根據(jù)實(shí)際情況,編寫默認(rèn)的構(gòu)造函數(shù)或SetUp()函數(shù),來為每個(gè) test 準(zhǔn)備所需內(nèi)容;
- 根據(jù)實(shí)際情況,編寫默認(rèn)的析構(gòu)函數(shù)或TearDown()函數(shù),來釋放SetUp()中分配的資源;
- 根據(jù)實(shí)際情況,定義 test 共享的子程序。
不同用例之間,數(shù)據(jù)實(shí)際都是獨(dú)占的,不會(huì)相互影響。
TEST_F()宏的第一個(gè)參數(shù)(即Test Case的名稱)必須是測試裝置類的類名。
對(duì)于TEST_F()定義的每個(gè)Test,Google Test將會(huì)在運(yùn)行時(shí)創(chuàng)建一個(gè)新的測試裝置對(duì)象,并立即通過SetUp()對(duì)其進(jìn)行初始化,然后運(yùn)行這個(gè)Test,之后通過TearDown()進(jìn)行數(shù)據(jù)清理,最后刪除測試裝置對(duì)象。==同一個(gè)Test Case中不同的test具有不同的測試裝置對(duì)象,并且Google Test每次創(chuàng)建新的測試裝置前都會(huì)先刪除之前的測試裝置。==多個(gè)Test不會(huì)重用相同的測試裝置,某個(gè)Test對(duì)測試裝置進(jìn)行修改對(duì)其他Test無影響。
#include "gtest/gtest.h" #include "MyStack.h" //MyStackTest繼承于testing命名空間下的Test類 class MyStackTest : public testing :: Test { protected: //總是在測試用例開始時(shí)被調(diào)用 virtual void SetUp() { st.push(34); st.push(28); st.push(56); } //總是在測試用例結(jié)束后被調(diào)用 virtual void TearDown() { } //構(gòu)造函數(shù),也可以做一部分SetUp函數(shù)的工作 MyStackTest() { std::cout << "MyStackTest is constructed." << std::endl; st.push(22); } //析構(gòu)函數(shù),也可以做一部分TearDown函數(shù)的工作 ~MyStackTest() { std::cout << "Destructed MyStackTest." << std::endl; } MyStack st; }; //如果使用了測試裝置,就必須使用TEST_F(測試裝置類, 自定義名稱) TEST_F(MyStackTest, testPop) { //在這里會(huì)自動(dòng)構(gòu)造一個(gè)MyStack的實(shí)例,并調(diào)用SetUp函數(shù) int val = st.pop(); EXPECT_EQ(56, val); //在這里會(huì)調(diào)用TearDown函數(shù) } //testPop2和testPop來自同一個(gè)測試裝置,但是來自不同的測試裝置實(shí)例,兩個(gè)實(shí)例是相互獨(dú)立的個(gè)體 TEST_F(MyStackTest, testPop2) { //在這里會(huì)自動(dòng)構(gòu)造一個(gè)MyStack的實(shí)例,并調(diào)用SetUp函數(shù) int val = st.pop(); EXPECT_EQ(56, val); //在這里會(huì)調(diào)用TearDown函數(shù) }
-
全局事件
要實(shí)現(xiàn)全局事件,必須寫一個(gè)類,繼承testing::Environment類,==定義一個(gè)該全局環(huán)境的一個(gè)對(duì)象并將該對(duì)象添加到全局環(huán)境測試中去。==實(shí)現(xiàn)里面的SetUp和TearDown成員函數(shù)。SetUp在所有案例執(zhí)行前執(zhí)行,TearDown在所有案例執(zhí)行后執(zhí)行。文章來源:http://www.zghlxwxcb.cn/news/detail-464710.html
#include "gtest/gtest.h" class GlobalTest : public testing::Environment { public: void SetUp() { std::cout << "SetUp" << std::endl; } void TearDown() { std::cout << "TearDown" << std::endl; } }; TEST(abs_test, test_1) { EXPECT_EQ(std::abs(-1), 1); } TEST(abs_test, test_2) { EXPECT_EQ(std::abs(0), 0); } int main(int argc, char **argv) { std::cout << "Running main() from gtest_main.cc\n"; testing::InitGoogleTest(&argc, argv); testing::Environment* env = new GlobalTest(); testing::AddGlobalTestEnvironment(env); return RUN_ALL_TESTS();//將會(huì)搜索所有已經(jīng)存在測試案例,然后運(yùn)行他們 }
-
死亡測試文章來源地址http://www.zghlxwxcb.cn/news/detail-464710.html
ASSERT_DEATH(參數(shù)1, 參數(shù)2);//程序掛了并且錯(cuò)誤信息和參數(shù)2匹配,此時(shí)認(rèn)為測試通過。如果參數(shù)2為空字符串,則只需要看程序掛沒掛即可。 ASSERT_EXIT(參數(shù)1, 參數(shù)2);//語句停止并且錯(cuò)誤信息和被提前給的信息匹配。
到了這里,關(guān)于GoogleTest從入門到入門,小白都能看懂的gtest詳細(xì)教程的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!