了解Google Test(gtest)

一、簡介

Google Test也叫gtest,是一個面向C++的單元測試框架。它在Google公司內部使用了多年,並且每天都在上千個項目中進行着單元測試。現在已經成為了C++單元測試的事實標準之一。gtest以其高效、靈活、可移植和可擴展等優點獲得廣泛好評。

二、gtest的基本結構

gtest最基本的結構可以分成兩部分:測試用例和測試夾具。測試用例是指對某一個功能的測試,通常會包含多個測試點。每個測試點對應一個gtest宏:TEST,通過TEST來定義測試用例並添加測試點。測試夾具是在每次測試運行之前和之後執行的代碼,用以準備測試環境和清理測試環境。

下面是一個示例代碼:

#include "gtest/gtest.h"
 
TEST(TestCaseName, TestName) {
  ...屬於這個測試用例的測試點1...
  ...屬於這個測試用例的測試點2...
  ...屬於這個測試用例的測試點3...
}

在這個例子中,”TestCaseName”和”TestName”分別是測試用例的名稱和測試點的名稱。在一個測試用例中可以定義多個測試點,但是測試用例名稱必須保持唯一。

三、gtest調試相關

1、gtest調試信息輸出

gtest在測試運行過程中,可以輸出調試信息,從而幫助我們定位問題。在gtest中,使用GTEST_COUT可以方便地輸出調試信息。

下面是一個示例代碼:

#include "gtest/gtest.h"
 
TEST(TestCaseName, TestName) {
    GTEST_COUT << "This is debug info!" << std::endl;
}

在這個例子中,代碼輸出了一條調試信息:”This is debug info!”。輸出的位置將在測試運行結果中顯示。

2、gtest運行調試器

如果我們需要在某個測試點處運行調試器,可以使用gtest的”–gtest_filter”參數來實現。

下面是一個示例代碼:

#include "gtest/gtest.h"
 
TEST(TestCaseName, TestName) {
    GTEST_COUT << "I am going to break point!" << std::endl;
    int a = 1;
    int b = 2;
    EXPECT_EQ(a + b, 3);
}

如果我們想在”EXPECT_EQ(a + b, 3)”處打一個斷點來進行調試,可以按下面的命令來執行:

./test --gtest_filter=TestCaseName.TestName:Test.DoDebugBreakHere

在這個例子中,我們通過在測試點後面加上”:Test.DoDebugBreakHere”的方式,在指定的測試點處讓程序停止。

3、gtest調式內存泄漏檢測

gtest提供了內存泄漏檢測,可以幫助我們檢測程序運行過程中是否有堆內存泄漏。

下面是一個示例代碼:

#include "gtest/gtest.h"
 
class Foo {
public:
    int* data;
    Foo() {
        data = new int[100];
    }
    virtual ~Foo() {
        delete[] data;
    }
};
 
TEST(TestCaseName, TestName) {
    GTEST_COUT << "This is to test memory leak!" <data[99] == 0);
}

在這個例子中,我們故意將Foo的data成員分配了100個整形內存,但是在Foo的析構函數中只釋放了1個整形內存。這樣就會造成堆內存泄漏。我們可以使用gtest的”–gtest_filter”參數,加上”–gtest_enable_death_test”選項來運行這個測試用例。

./test --gtest_filter=TestCaseName.TestName --gtest_enable_death_test

這樣運行測試用例後,gtest會檢測到內存泄漏,並在屏幕上輸出相關信息。

四、gtest運行方式

gtest有三種運行方式:在命令行運行、在IDE中運行、在自動化構建工具中運行。

1、在命令行運行

在命令行下運行gtest非常簡單,只需要將gtest庫鏈接到測試程序中,然後用”./test”來運行測試程序即可。gtest提供了豐富的啟動選項,如”–gtest_list_tests”,”–gtest_filter”等。

下面是一個運行gtest的例子:

gtest_main.cc:
#include "gtest/gtest.h"
 
GTEST_API_ int main(int argc, char **argv)
{
    testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}

下面是編譯gtest庫的默認Makefile:

GTEST_DIR = ../googletest
CXXFLAGS += -isystem $(GTEST_DIR)/include
CXXFLAGS += -std=c++11 -g -Wall -Wextra -pthread
TESTS = first_test.cpp second_test.cpp
 
all : test
test : $(TESTS) gtest_main.a
    $(CXX) $(CXXFLAGS) -o $@ $^
 
gtest-all.o : $(GTEST_DIR)/src/gtest-all.cc $(GTEST_DIR)/include/gtest/gtest.h
    $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(GTEST_DIR)/src/gtest-all.cc
 
gtest_main.o : $(GTEST_DIR)/src/gtest_main.cc $(GTEST_DIR)/include/gtest/gtest.h
    $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(GTEST_DIR)/src/gtest_main.cc
 
gtest_main.a : gtest-all.o gtest_main.o
    $(AR) $(ARFLAGS) $@ $^

2、在IDE中運行

大多數現代IDE都已經支持gtest的執行,運行gtest的過程就像運行其他可執行程序一樣。以Visual Studio為例,可以使用選項”/MDd”將gtest和測試程序鏈接在一起,然後可以用F5來啟動調試會話。

3、在自動化構建工具中運行

gtest可以與許多常見自動化構建工具一起使用,如Make、Ant、CMake、MSBuild等。下面是使用CMake來運行gtest的一個示例代碼:

cmake_minimum_required(VERSION 3.10.2)
project(MyTest)
enable_testing()
add_executable(MyTest test.cc)
target_link_libraries(MyTest gtest_main gtest)
add_test(MyTest MyTest)

在這個例子中,我們先使用add_executable來定義要測試的程序,然後再使用target_link_libraries將gtest庫鏈接到程序中。最後,我們使用add_test將MyTest這個測試添加到測試套件中。

五、gtest的擴展功能

gtest提供了許多非常有用的擴展功能,讓我們能更好地管理測試用例和測試點,以及對程序進行更細緻的驗證。

1、在gtest中組織測試用例

如果我們需要對一組相關的測試用例進行分類,可以使用gtest的TEST_F宏定義來組織測試用例。在TEST_F中定義fixture類來提供測試夾具。

下面是一個示例代碼:

#include "gtest/gtest.h"
 
class TestFixture: public testing::Test {
public:
    static void SetUpTestCase() {}
    static void TearDownTestCase() {}
    virtual void SetUp() {}
    virtual void TearDown() {}
};
 
TEST_F(TestFixture, TestName) {
    GTEST_COUT << "This is a test!" << std::endl;
}

在這個例子中,TestFixture定義了SetUpTestCase和TearDownTestCase來執行測試夾具的初始化和清理任務,SetUp和TearDown來執行每個測試點的初始化和清理任務。使用TEST_F來定義測試用例和測試點。

2、EXPECT系列驗證宏

gtest提供了一系列EXPECT_*和ASSERT_*宏來對程序進行驗證。EXPECT_*和ASSERT_*宏有一點區別,雖然它們都會做出判斷,但EXPECT_*將驗證結果記錄下來,不管是否驗證成功都繼續執行;而ASSERT_*則在驗證失敗的時候立即停止程序。以下是常用的EXPECT系列驗證宏:

  • EXPECT_EQ(val1, val2) – val1 == val2
  • EXPECT_NE(val1, val2) – val1 != val2
  • EXPECT_LT(val1, val2) – val1 < val2
  • EXPECT_LE(val1, val2) – val1 <= val2
  • EXPECT_GT(val1, val2) – val1 > val2
  • EXPECT_GE(val1, val2) – val1 >= val2
  • EXPECT_TRUE(condition) – condition is true.
  • EXPECT_FALSE(condition) – condition is false.

下面是一個示例代碼:

#include "gtest/gtest.h"
 
TEST(TestCaseName, TestName) {
    EXPECT_EQ(1, 1) << "1 equals 1";
    EXPECT_NE(1, 2) << "1 not equals 2";
    EXPECT_TRUE(0 == 0) << "0 == 0";
    EXPECT_FALSE(1 == 2) << "1 not equals 2";
}

3、自己編寫gtest擴展功能

我們可以通過編寫gtest插件的方式來擴展gtest的功能。gtest插件可以實現事件響應、輸出擴展、斷言擴展和異常捕獲等功能。

以下是一個gtest插件的實現示例:

#include "gtest/gtest.h"
 
void MyTestEventListener::OnTestStart(const testing::TestInfo& test_info) {
    std::cout << "Test start: " << test_info.name() << std::endl;
    fflush(stdout); //刷新輸出緩衝區,即將緩衝區的內容立即輸出
}
 
void MyTestEventListener::OnTestEnd(const testing::TestInfo& test_info) {
    std::cout << "Test end: " << test_info.name() <listeners();
    listeners.Append(new MyTestEventListenerFactory);
 
    EXPECT_TRUE(1 == 1);
}

在這個示例中,我們編寫了一個gtest插件,用來在測試開始和測試結束時打印一條信息。我們使用listeners.Append將這個插件添加到事件監聽器列表中。在TestName測試點中,我們使用了EXPECT_TRUE宏來對程序進行驗證。

六、結論

Google Test是一個非常好用的C++單元測試框架,具有高效、靈活、可移植和可擴展等優點。通過增強gtest的認識和學習如何使用gtest將有助於我們編寫更高效、更健壯的C++程序。

原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hk/n/293572.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
小藍的頭像小藍
上一篇 2024-12-26 13:14
下一篇 2024-12-26 13:14

相關推薦

  • Sublime Test與Python的區別

    Sublime Text是一款流行的文本編輯器,而Python是一種廣泛使用的編程語言。雖然Sublime Text可以用於編寫Python代碼,但它們之間有很多不同之處。接下來從…

    編程 2025-04-29
  • Python2-Google-AppUtils

    如果你正在尋找一種用於編寫可擴展性和易維護性良好的Python2應用程序的方法,那麼Python2-Google-AppUtils是你的最佳選擇。該工具集提供了豐富的功能和工具,可…

    編程 2025-04-28
  • Ubuntu Google: 全方位開發工程師的首選

    一、Ubuntu Google概述 Ubuntu是一款自由開源的操作系統,採用Debian GNU/Linux發行版和GNOME桌面環境,它被認為是最易於使用的Linux,並且能夠…

    編程 2025-04-25
  • 如何解決「There are test failures」

    一、檢查測試代碼 首先,我們需要檢查測試代碼本身是否出了問題。如果你發現測試代碼的輸入/輸出邏輯出了問題,那麼你需要修改測試代碼並再次運行測試。同時你還可以添加更多的測試用例來保證…

    編程 2025-02-24
  • Google Fonts——web 設計中的免費字體之選

    一、入門使用 Google Fonts Google Fonts 是一項可以免費使用的字體服務,網站設計人員可以通過它,為其網站選擇適合的字體。在 Google Fonts 中有超…

    編程 2025-02-05
  • 深入了解Google瀏覽器清除緩存

    一、Google瀏覽器清除緩存怎麼操作 如果在使用Google瀏覽器的過程中,感覺網頁加載速度變慢,或者顯示不正常,可能是由於瀏覽器緩存造成的。這時,我們需要清除瀏覽器緩存。可以通…

    編程 2025-01-20
  • Google不支持Flash怎麼辦

    一、什麼是Flash? Flash是Adobe公司開發的一種跨平台的應用程序和富媒體內容創作工具,主要用於製作網站動畫、廣告、遊戲等。但隨着HTML5的普及,Flash已經逐漸被淘…

    編程 2025-01-20
  • Google高級搜索的使用技巧

    一、搜索結果的過濾 Google高級搜索提供了許多過濾搜索結果的選項,讓用戶可以更加精確地找到自己需要的信息。其中常用的過濾選項有: 語言:用戶可根據自己的語言需求選擇搜索結果的語…

    編程 2025-01-14
  • Google瀏覽器歷史版本

    一、起源 Google Chrome瀏覽器最初於2008年發佈,這個瀏覽器以其速度、可靠性和易用性而聞名,成為了互聯網上最受歡迎的瀏覽器之一。從版本1.0開始,Chrome就享受着…

    編程 2025-01-13
  • Google DNS 8.8.8.8

    一、DNS基礎知識 DNS(Domain Name System),即域名系統,是互聯網的一項服務。它作為將域名和IP地址相互映射的一個分佈式數據庫,能夠使人更方便地訪問互聯網上的…

    編程 2025-01-02

發表回復

登錄後才能評論