google c++程序測試框架googletest使用教程詳解
什么是googletest?
googletest簡介
GoogleTest 是 Google 的 C++ 測試和模擬框架,可以幫助程序員測試C++程序的結(jié)果預(yù)期,GoogleTest 的代碼用cmake管理,可以使用cmake進(jìn)行編譯程dll在程序中使用。googletest一般也可以簡稱為gtest, 最新版本GoogleTest 需要符合 C++11 標(biāo)準(zhǔn)或更新標(biāo)準(zhǔn)的代碼庫和編譯器。
gtest官網(wǎng):https://google.github.io/googletest/
git倉庫:https://github.com/google/googletest
誰在使用 GoogleTest?
除了 Google 的許多內(nèi)部項目,GoogleTest 還被以下著名項目使用:
- 該鉻項目(Chrome瀏覽器和Chrome OS背后)。
- 該LLVM編譯器。
- Protocol Buffers,Google 的數(shù)據(jù)交換格式。
- 在OpenCV的計算機(jī)視覺庫。 相關(guān)開源項目
相關(guān)開源項目
GTest Runner是一個基于 Qt5 的自動化測試運行器和圖形用戶界面,具有適用于 Windows 和 Linux 平臺的強大功能。
GoogleTest UI是一個測試運行器,它運行您的測試二進(jìn)制文件,允許您通過進(jìn)度條跟蹤其進(jìn)度,并顯示測試失敗列表。單擊一個顯示失敗文本。GoogleTest UI 是用 C# 編寫的。
GTest TAP Listener是GoogleTest 的一個事件監(jiān)聽器,它實現(xiàn)了測試結(jié)果輸出的 TAP 協(xié)議。如果您的測試運行器了解 TAP,您可能會發(fā)現(xiàn)它很有用。
gtest-parallel是一個測試運行器,它并行運行來自二進(jìn)制文件的測試以提供顯著的加速。
GoogleTest Adapter 是一個 VS Code 擴(kuò)展,允許在樹視圖中查看 GoogleTest,并運行/調(diào)試您的測試。
C++ TestMate是一個 VS Code 擴(kuò)展,允許在樹視圖中查看 GoogleTest,并運行/調(diào)試您的測試。
Cornichon是一個小型 Gherkin DSL 解析器,可為 GoogleTest 生成存根代碼。
googletest的下載與編譯
github鏈接:https://github.com/google/googletest
cmake gui編譯
添加代碼路徑和生成后的目錄,點擊configure, 我編譯的是win32版本
增加一個編譯選項 CMAKE_DEBUG_POSTFIX,類型為STRING, value為 _d(這個隨便寫,只是為了區(qū)分debug和release的
庫)這樣編譯后的debug庫就會自帶一個d后綴,與release的好區(qū)分。
點擊generate
出現(xiàn)以上結(jié)果表示sln生成ok, 點擊open project即可打開項目,一共66個子項目,其中有l(wèi)ib和googletest的測試代碼。
右鍵INSTALL項目,生成解決方案,即可把.h .lib .dll 提取到cmake編譯時設(shè)置的CMAKE_INSTALL_PREFIX目錄里,我的生成結(jié)果:
bin目錄里是dll
很多項目都可以用cmake進(jìn)行編譯,只要在源碼根目錄看到了CMakeLists.txt, 那么這種項目就可以使用cmake進(jìn)行編譯,比如:
- VTK
- OpenCV
- jsoncpp
- log4cplus
- googletest
- google chromium
- webrtc
- glog
- 還有很多 。。。
在vs2019中使用googletest
一般編譯后,都是.h .lib .dll, 在vs中進(jìn)行配置就可以使用,下面是gtest的測試代碼:
#include <iostream> #include "gtest/gtest.h" #pragma comment(lib, "gtestd.lib") int add(int a, int b) { return a + b; } //編寫測試case TEST(testCase, test0) { EXPECT_EQ(add(2, 3), 5); //判斷結(jié)果是不是等于5,EXPECT_EQ表示 "等于" } int main(int argc, char** argv) { testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); }
運行結(jié)果
GTest的一些基本概念
要測試一個類或函數(shù),我們需要對其行為做出斷言。當(dāng)一個斷言失敗時,Google Test會在屏幕上輸出該代碼所在的源文件及其所在的位置行號,以及錯誤信息。也可以在編寫斷言時,提供一個自定義的錯誤信息,這個信息在失敗時會被附加在Google Test的錯誤信息之后。
斷言常常成對出現(xiàn),它們都測試同一個類或者函數(shù),但對當(dāng)前功能有著不同的效果。ASSERT_*版本的斷言失敗時會產(chǎn)生致命失敗,并結(jié)束當(dāng)前函數(shù)。EXPECT_*版本的斷言產(chǎn)生非致命失敗,而不會中止當(dāng)前函數(shù)。通常更推薦使用EXPECT_*斷言,因為它們運行一個測試中可以有不止一個的錯誤被報告出來。但如果在編寫斷言如果失敗,就沒有必要繼續(xù)往下執(zhí)行的測試時,你應(yīng)該使用ASSERT_*斷言。 因為失敗的ASSERT_*斷言會立刻從當(dāng)前的函數(shù)返回,可能會跳過其后的一些的清潔代碼,這樣也許會導(dǎo)致空間泄漏。
GTest的斷言
1、布爾值檢查
Fatal assertion | Nonfatal assertion | Verifies |
---|---|---|
ASSERT_TRUE(condition); | EXPECT_TRUE(condition); | condition is true |
ASSERT_FALSE(condition); | EXPECT_FALSE(condition); | condition is false |
2、數(shù)值型數(shù)據(jù)檢查
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 |
3、字符串比較
Fatal assertion | Nonfatal assertion | Verifies |
---|---|---|
ASSERT_STREQ(expected_str, actual_str); | EXPECT_STREQ(expected_str, actual_str); | 兩個C字符串有相同的內(nèi)容 |
ASSERT_STRNE(str1, str2); | EXPECT_STRNE(str1, str2); | 兩個C字符串有不同的內(nèi)容 |
ASSERT_STRCASEEQ(expected_str, actual_str); | EXPECT_STRCASEEQ(expected_str, actual_str); | 兩個C字符串有相同的內(nèi)容,忽略大小寫 |
ASSERT_STRCASENE(str1, str2); | EXPECT_STRCASENE(str1, str2); | 兩個C字符串有不同的內(nèi)容,忽略大小寫 |
4、異常檢查
Fatal assertion | Nonfatal assertion | Verifies |
---|---|---|
ASSERT_THROW(statement, exception_type); | EXPECT_THROW(statement, exception_type); | statement throws an exception of the given type |
ASSERT_ANY_THROW(statement); | EXPECT_ANY_THROW(statement); | statement throws an exception of any type |
ASSERT_NO_THROW(statement); | EXPECT_NO_THROW(statement); | statement doesn't throw any exception |
5、浮點型檢查
Fatal assertion | Nonfatal assertion | Verifies |
---|---|---|
ASSERT_FLOAT_EQ(expected, actual); | EXPECT_FLOAT_EQ(expected, actual); | the two float values are almost equal |
ASSERT_DOUBLE_EQ(expected, actual); | EXPECT_DOUBLE_EQ(expected, actual); | the two double values are almost equal |
對相近的兩個數(shù)比較:
Fatal assertion | Nonfatal assertion | Verifies |
---|---|---|
ASSERT_NEAR(val1, val2, abs_error); | EXPECT_NEAR*(val1, val2, abs_error*); | the difference between val1 and val2 doesn't exceed the given absolute error |
6、此外還有類型檢查、謂詞檢查等
事件機(jī)制
全局事件
要實現(xiàn)全局事件,必須寫一個類,繼承testing::Environment類,實現(xiàn)里面的SetUp和TearDown方法。
- SetUp()方法在所有案例執(zhí)行前執(zhí)行
- TearDown()方法在所有案例執(zhí)行后執(zhí)行
還需要告訴gtest添加這個全局事件,我們需要在main函數(shù)中通過testing::AddGlobalTestEnvironment方法將事件掛進(jìn)來,也就是說,我們可以寫很多個這樣的類,然后將他們的事件都掛上去。
TestSuite事件
我們需要寫一個類,繼承testing::Test,然后實現(xiàn)兩個靜態(tài)方法
- SetUpTestCase() 方法在第一個TestCase之前執(zhí)行
- TearDownTestCase() 方法在最后一個TestCase之后執(zhí)行
在編寫測試案例時,我們需要使用TEST_F這個宏,第一個參數(shù)必須是我們上面類的名字,代表一個TestSuite。
TestCase事件
TestCase事件是掛在每個案例執(zhí)行前后的,實現(xiàn)方式和上面的幾乎一樣,不過需要實現(xiàn)的是SetUp方法和TearDown方法:
- SetUp()方法在每個TestCase之前執(zhí)行
- TearDown()方法在每個TestCase之后執(zhí)行
以下案例解決說明上述三個事件的使用
#include <iostream> #include <map> #include "gtest/gtest.h" #pragma comment(lib, "gtestd.lib") using namespace std; class Student { public: Student() { age = 0; } Student(int a) { age = a; } void print() { cout << "*********** " << age << " **********" << endl;; } private: int age; }; class FooEnvironment : public testing::Environment { public: virtual void SetUp() { std::cout << "Foo FooEnvironment SetUP" << std::endl; } virtual void TearDown() { std::cout << "Foo FooEnvironment TearDown" << std::endl; } }; static Student* s; //在第一個test之前,最后一個test之后調(diào)用SetUpTestCase()和TearDownTestCase() class TestMap :public testing::Test { public: static void SetUpTestCase() { cout << "SetUpTestCase()" << endl; s = new Student(23); } static void TearDownTestCase() { delete s; cout << "TearDownTestCase()" << endl; } void SetUp() { cout << "SetUp() is running" << endl; } void TearDown() { cout << "TearDown()" << endl; } }; TEST_F(TestMap, Test1) { // you can refer to s here s->print(); } int main(int argc, char** argv) { testing::AddGlobalTestEnvironment(new FooEnvironment); testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); }
運行結(jié)果
參數(shù)化
當(dāng)考慮多次要為被測函數(shù)傳入不同的值的情況時,可以按下面的方式去測試。必須添加一個類,繼承testing::TestWithParam。其中T就是你需要參數(shù)化的參數(shù)類型,如下面的案例是int型參數(shù)。(官方文檔上的案例)
#include<gtest/gtest.h> // Returns true iff n is a prime number. bool IsPrime(int n) { // Trivial case 1: small numbers if (n <= 1) return false; // Trivial case 2: even numbers if (n % 2 == 0) return n == 2; // Now, we have that n is odd and n >= 3. // Try to divide n by every odd number i, starting from 3 for (int i = 3; ; i += 2) { // We only have to try i up to the squre root of n if (i > n/i) break; // Now, we have i <= n/i < n. // If n is divisible by i, n is not prime. if (n % i == 0) return false; } // n has no integer factor in the range (1, n), and thus is prime. return true; } class IsPrimeParamTest : public::testing::TestWithParam<int>{}; TEST_P(IsPrimeParamTest, HandleTrueReturn) { int n = GetParam(); EXPECT_TRUE(IsPrime(n)); } //被測函數(shù)須傳入多個相關(guān)的值 INSTANTIATE_TEST_CASE_P(TrueReturn, IsPrimeParamTest, testing::Values(3, 5, 11, 23, 17)); int main(int argc, char **argv) { testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); }
gtest的使用就介紹這么多,大家有興趣的話,可以加到自己的C++項目中做代碼測試。
到此這篇關(guān)于google c++程序測試框架googletest使用教程的文章就介紹到這了,更多相關(guān)c++程序測試框架googletest內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
通過c語言調(diào)用系統(tǒng)curl動態(tài)庫的示例詳解
這篇文章中我們將通過一個簡單的示例來講解如何在Ubuntu系統(tǒng)中通過C語言調(diào)用動態(tài)庫(共享庫)的方法,我們將使用libcurl庫,這是一個基于客戶端的URL傳輸庫,廣泛用于各種程序和應(yīng)用中以訪問網(wǎng)頁和服務(wù)器數(shù)據(jù),需要的朋友可以參考下2024-03-03C/C++實現(xiàn)動態(tài)數(shù)組的示例詳解
動態(tài)數(shù)組相比于靜態(tài)數(shù)組具有更大的靈活性,因為其大小可以在運行時根據(jù)程序的需要動態(tài)地進(jìn)行分配和調(diào)整,本文為大家介紹了C++實現(xiàn)動態(tài)數(shù)組的方法,需要的可以參考下2023-08-08