Qt 中使用 gtest 做單元測試

作者:billy
版權聲明:著作權歸作者所有,商業轉載請聯系作者獲得授權,非商業轉載請注明出處

gtest 簡介

GoogleTest(也稱為gtest)是由 Google 開發的一個 C++ 單元測試框架,用于編寫、組織和運行自動化測試代碼。它支持斷言(如 EXPECT_EQ、ASSERT_TRUE 等)、測試夾具(test fixtures)、參數化測試等高級功能,能夠幫助開發者在開發過程中快速發現和定位問題。GoogleTest 具有良好的跨平臺性,廣泛用于 C++ 項目的測試驗證,是工業界最常用的 C++ 測試框架之一

構建

gtest 源代碼下載:github 下載
百度網盤下載:下載鏈接
提取碼: kjef

百度網盤里除了源代碼,還有編譯好的動態庫可以直接使用,編譯環境是 vs2019 64位
在這里插入圖片描述
在 qt 中使用 gtest 需要導入依賴庫,把 googletest_msvc2019 文件夾放在 pro 文件同目錄下,然后在 pro 文件中添加以下信息:

INCLUDEPATH += $$PWD/googletest_msvc2019/includewin32:CONFIG(release, debug|release): {LIBS += -L$$PWD/googletest_msvc2019/lib/Release/ -lgmockLIBS += -L$$PWD/googletest_msvc2019/lib/Release/ -lgmock_mainLIBS += -L$$PWD/googletest_msvc2019/lib/Release/ -lgtestLIBS += -L$$PWD/googletest_msvc2019/lib/Release/ -lgtest_main
}
else:win32:CONFIG(debug, debug|release): {LIBS += -L$$PWD/googletest_msvc2019/lib/Debug/ -lgmockLIBS += -L$$PWD/googletest_msvc2019/lib/Debug/ -lgmock_mainLIBS += -L$$PWD/googletest_msvc2019/lib/Debug/ -lgtestLIBS += -L$$PWD/googletest_msvc2019/lib/Debug/ -lgtest_main
}

gtest 語法

1. TEST

這是定義測試用例的基本宏。它接受兩個參數:測試用例的名稱和一個測試函數

TEST(TestSuiteName, TestName) {  // 測試代碼  
}

2. TEST_F

用于定義繼承自某個測試夾具(Test Fixture)的測試。測試夾具是一個類,用于設置測試前的環境和清理測試后的環境。TEST_F 宏接受兩個參數:測試夾具的類名和測試名稱

class MyFixture : public ::testing::Test {  
protected:  // 設置測試環境  void SetUp() override {  // 初始化代碼  }  // 清理測試環境  void TearDown() override {  // 清理代碼  }  
};  TEST_F(MyFixture, TestName) {  // 測試代碼  
}

3. TEST_P

用于定義參數化測試。參數化測試允許你運行同一個測試代碼,但是使用不同的參數集。首先,你需要定義一個測試夾具類并繼承自 ::testing::TestWithParam,其中T是參數的類型。然后,使用 TEST_P 宏定義測試

class MyParameterizedTest : public ::testing::TestWithParam<int> {  
protected:  void SetUp() override {  // 使用GetParam()獲取參數  }  
};  TEST_P(MyParameterizedTest, TestName) {  // 測試代碼,使用GetParam()獲取參數  
}  INSTANTIATE_TEST_SUITE_P(instanceName, MyParameterizedTest, ::testing::Values(1, 2, 3, 4));

4. SCOPED_TRACE

用于在測試失敗時添加額外的日志信息的宏。它在日志消息中添加一個額外的文本信息,這對于理解測試失敗時的上下文非常有用。通常與 EXPECT_ 或 ASSERT_ 宏一起使用,以便在測試失敗時提供更多的調試信息

SCOPED_TRACE("SubFunction called with value " << value);

5. EXPECT_ 和 ASSERT_ 系列宏

這些宏用于在測試中驗證代碼的行為。EXPECT_ 系列的宏在遇到失敗時會記錄錯誤并繼續執行測試中的后續語句,而 ASSERT_ 系列的宏在遇到失敗時會記錄錯誤并終止當前測試。下面以非致命斷言 EXPECT_ 系列為例:

非致命斷言結果
EXPECT_TRUE(condition)檢查 condition 是否為真
EXPECT_FALSE(condition)檢查 condition 是否為假
--
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_STREQ(str1, str2)用于比較兩個C字符串是否相等
EXPECT_STRNE(str1, str2)用于比較兩個C字符串是否不相等
EXPECT_STRCASEEQ(str1, str2)用于比較兩個C字符串是否相等,?忽略字母大小寫差異
EXPECT_STRCASENE(str1, str2)用于比較兩個C字符串是否不相等,?忽略字母大小寫差異
--
EXPECT_FLOAT_EQ(val1, val2)檢測浮點數 val1 和 val2 是否相等,允許一定的誤差
EXPECT_DOUBLE_EQ(val1, val2)檢測雙精度浮點數 val1 和 val2 是否相等,允許一定的誤差
EXPECT_NEAR(val1, val2, abs_error)檢查浮點數 val1 和 val2 的差值的絕對值是否小于或等于 abs_error
--
EXPECT_THROW(statement, expected_exception)檢測 statement 是否拋出指定類型的異常 expected_exception
EXPECT_ANY_THROW(statement)檢測 statement 是否拋出任何異常
ASSERT_NO_THROW(statement)檢測 statement 是否不拋出異常
--
EXPECT_DEATH(statement, regex)用于測試在執行 statement 時是否會導致程序崩潰,并且崩潰信息是否符合正則表達式 regex 的要求
EXPECT_THAT(actual, matcher)用于進行復雜的條件檢查,特別是在使用匹配器時。matcher 用于檢查 actual 的匹配器

6. SUCCEED 和 FAIL

SUCCEED() 會標記當前測試用例成功并立即結束測試。無論之前的測試代碼是否存在錯誤,都會標記為成功,并且SUCCEED 后面的代碼不會被執行
FAIL() 會標記當前測試用例為失敗并立即結束測試。可以用來在測試代碼中發現不可接受的狀態時報告測試失敗。在 FAIL() 之后的代碼不會被執行。可以 FAIL() << “ ”;用于在測試失敗后輸出一段信息

7. ADD_FAILURE 和 ADD_FAILURE_AT

ADD_FAILURE 用于手動添加測試失敗的報告,而不依賴于某個特定斷言的失敗。可以在代碼中的任何一個位置來標記,當執行到 ADD_FAILUR 時,gtest 會報告測試失敗,但程序仍然會繼續執行后續的代碼
ADD_FAILURE_AT 允許在指定的文件名和行號處報告失敗

Qt 中的應用示例

// 源代碼功能:加載一個json文件存儲在內存中
QJsonObject CommonFunction::getObjFromConfig(QString fileName)
{QFileInfo fileInfo(fileName);if ( !fileInfo.isFile() ) {return QJsonObject();}QFile file(fileName);if ( !file.open(QIODevice::ReadOnly) ) {return QJsonObject();}// get json objectQByteArray jsonData = file.readAll();// QString jsonString = QString::fromUtf8(jsonData);// qDebug() << jsonString;file.close();QJsonDocument jsonDoc(QJsonDocument::fromJson(jsonData));QJsonObject obj = jsonDoc.object();return obj;
}

創建一個頭文件 test_getObjFromConfig.h 編寫單元測試代碼

#ifndef TEST_GETOBJFROMCONFIG_H
#define TEST_GETOBJFROMCONFIG_H#include <gtest/gtest.h>
#include "commonfunction.h"
#include <QTemporaryFile>class Test_GetObjFromConfig : public testing::Test
{
protected:CommonFunction* commonFun;void SetUp() override {commonFun = new CommonFunction();}void TearDown() override {delete commonFun;}
};// 測試文件不存在的情況
TEST_F(Test_GetObjFromConfig, FileNotFoundReturnsEmptyObject) {QString nonExistentFile = "non_existent_file.json";QJsonObject result = commonFun->getObjFromConfig(nonExistentFile);EXPECT_TRUE(result.isEmpty());
}// 測試文件無法打開的情況(例如:沒有權限)
TEST_F(Test_GetObjFromConfig, UnreadableFileReturnsEmptyObject) {// 創建一個臨時文件并立即關閉它QTemporaryFile tempFile("XXXXXX.json");tempFile.open();tempFile.close();// 設置文件權限為只讀(假設當前用戶無法寫入)QFile file(tempFile.fileName());file.setPermissions(QFile::ReadOwner);QJsonObject result = commonFun->getObjFromConfig(tempFile.fileName());EXPECT_TRUE(result.isEmpty());
}// 測試有效的JSON文件
TEST_F(Test_GetObjFromConfig, ValidJsonFileReturnsParsedObject) {// 創建臨時文件并寫入有效的JSON內容QTemporaryFile tempFile("XXXXXX.json");if (tempFile.open()) {QString jsonContent = R"({"company":"swyl"})";tempFile.write(jsonContent.toUtf8());tempFile.close();QJsonObject result = commonFun->getObjFromConfig(tempFile.fileName());EXPECT_FALSE(result.isEmpty());EXPECT_EQ(result["company"].toString(), "swyl");} else {FAIL() << "無法創建臨時文件";}
}// 測試無效的JSON文件
TEST_F(Test_GetObjFromConfig, InvalidJsonFileReturnsEmptyObject) {// 創建臨時文件并寫入無效的JSON內容QTemporaryFile tempFile("XXXXXX.json");if (tempFile.open()) {QString invalidJson = "invalid json content";tempFile.write(invalidJson.toUtf8());tempFile.close();QJsonObject result = commonFun->getObjFromConfig(tempFile.fileName());EXPECT_TRUE(result.isEmpty());} else {FAIL() << "無法創建臨時文件";}
}// 測試空JSON文件
TEST_F(Test_GetObjFromConfig, EmptyFileReturnsEmptyObject) {// 創建空的臨時文件QTemporaryFile tempFile("XXXXXX.json");if (tempFile.open()) {tempFile.close();QJsonObject result = commonFun->getObjFromConfig(tempFile.fileName());EXPECT_TRUE(result.isEmpty());} else {FAIL() << "無法創建臨時文件";}
}#endif // TEST_GETOBJFROMCONFIG_H

在這里插入圖片描述

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/86052.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/86052.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/86052.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

WPF TreeView 數據綁定完全指南:MVVM 模式實現

WPF TreeView 數據綁定完全指南&#xff1a;MVVM 模式實現 一、TreeView 綁定的核心概念1.1 MVVM 模式下的 TreeView 綁定原理1.2 綁定關系示意圖 二、完整實現步驟2.1 創建節點模型類2.2 創建 ViewModel2.3 XAML 綁定配置2.4 設置 Window 的 DataContext 三、關鍵特性詳解3.1 …

坤馳科技QTS4200戰鷹(Battle Eagle)系列實時頻譜分析記錄回放系統

QTS4200戰鷹(Battle Eagle)系列 實時頻譜分析記錄回放系統 精準采集&#xff5c;高效回放&#xff5c;拓展頻譜分析新邊界 坤馳科技傾力打造新一代集實時頻譜分析、高速信號記錄與精準信號回放于一體的便攜式系統&#xff0c;為無線電監測、無線通信、國防等領域提供全面而高…

Flask(二) 路由routes

文章目錄 基本路由定義路由參數路由規則設置請求方法&#xff08;GET/POST&#xff09;路由函數返回靜態文件和模板Blueprint&#xff08;模塊化路由&#xff09;顯示當前所有路由 Flask 路由是 Web 應用程序中將 URL 映射到 Python 函數的機制。 定義路由&#xff1a;使用 app…

在el-image組件的預覽中添加打印功能(自定義功能)

思路&#xff1a;給圖片添加點擊事件&#xff0c;通過js獲取預覽的工具欄&#xff0c;在工具欄中添加自定義按鈕及事件 1、html 中 image標簽 <el-image style"width: 139px; height: 89px" :src"fileUrl" :preview-src-list"[fileUrl]" cli…

TongWeb替換tomcat

1、背景 國家近年來大力推進信息技術應用創新產業&#xff08;信創&#xff09;&#xff0c;要求關鍵領域采用自主可控的國產軟硬件。Tomcat作為國外開源產品&#xff0c;存在潛在的安全風險和技術依賴。TongWeb作為國產中間件&#xff0c;符合信創目錄要求&#xff0c;滿足政府…

聯合語音和文本機器翻譯,支持多達100種語言(nature子刊論文研讀)

簡介&#xff1a; &#x1f30d; SEAMLESSM4T 是一種單一模型&#xff0c;實現了跨越多達 101 種源語言和多種目標語言的語音到語音、語音到文本、文本到語音和文本到文本翻譯及自動語音識別。&#x1f680; 該模型性能顯著超越現有級聯系統&#xff0c;特別是在語音到文本和語…

網站公安網安備案查詢API集成指南

網站公安網安備案查詢API集成指南 引言 隨著互聯網應用的日益普及&#xff0c;網絡安全和個人隱私保護越來越受到重視。公安網安備案作為保障網絡安全的重要措施之一&#xff0c;對于確保網站合法合規運營具有重要意義。為了幫助開發者更加便捷地獲取網站的公安網安備案信息&a…

如何用遠程調試工具排查 WebView 與原生通信問題(iOS或Android)

WebView 在移動端開發中的角色越來越關鍵&#xff0c;尤其在混合架構&#xff08;Hybrid&#xff09;項目中&#xff0c;它作為前端與原生的橋梁&#xff0c;承載了大量交互行為。但這個橋梁并不總是穩固&#xff0c;尤其是在涉及 JSBridge 通信 時&#xff0c;前端調用原生接口…

使用 spark-submit 運行依賴第三方庫的 Python 文件

python文件在spark集群運行真的麻煩&#xff0c;煩冗 spark運行分為了三個模式&#xff0c;本地模式/client模式/cluster模式 文章目錄 本地模式client模式cluster模式參考 本地模式 現在的spark支持python3了&#xff0c;支持python2的版本已經很落后了&#xff0c;所以需要…

【android bluetooth 協議分析 05】【藍牙連接詳解2】【acl_interface_t介紹】

1. acl_interface_t 介紹 acl_interface_t 結構體及其子結構體&#xff0c;目的是封裝處理 Classic、LE、SCO 連接及鏈路事件的回調函數&#xff0c;用于 HCI 事件與上層藍牙協議棧的解耦分發。 system/main/shim/acl_legacy_interface.h typedef struct {void (*on_connect…

TouchDIVER Pro觸覺手套:虛擬現實中的多模態交互新選擇

隨著虛擬現實技術的發展&#xff0c;用戶對沉浸式體驗的需求不斷提升。TouchDIVER Pro觸覺手套通過力反饋、紋理渲染和溫度提示三種核心機制&#xff0c;為用戶提供更真實的觸覺感知體驗。六個驅動點分布于五指與手掌&#xff0c;結合全手追蹤與低延遲連接&#xff0c;實現精準…

想考華為HCIA-AI,應該怎么入門?

華為HCIA-AI Solution認證作為華為人工智能認證體系的起點&#xff0c;吸引了許多希望進入AI領域或提升專業技能的學習者。如果你正考慮考取這個認證&#xff0c;這份純科普向的入門指南希望能夠幫你理清學習路徑和關鍵準備點&#xff01; 第一、明確認證目標與要求 HCIA-AI S…

【Oracle篇】Windows平臺單進程多線程架構設計與實現(比對Linux多進程架構)

&#x1f4ab;《博主主頁》&#xff1a; &#x1f50e; CSDN主頁__奈斯DB &#x1f50e; IF Club社區主頁__奈斯、 &#x1f525;《擅長領域》&#xff1a;擅長阿里云AnalyticDB for MySQL(分布式數據倉庫)、Oracle、MySQL、Linux、prometheus監控&#xff1b;并對SQLserver、N…

在微服務中使用 Sentinel

在微服務中集成 Sentinel 1. 添加依賴 對于 Spring Cloud 項目&#xff0c;首先需要添加 Sentinel 的依賴&#xff1a; <!-- Spring Cloud Alibaba Sentinel --> <dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-…

中斷控制與實現

一、中斷基本概念 1、中斷 中斷是一種異步事件&#xff0c;用于通知處理器某個事件已經發生&#xff0c;需要處理器立即處理。由于I/O操作的不確定因素以及處理器和I/O設備之間的速度不匹配&#xff0c;I/O設備可以通過某種硬件信號異步喚醒對應的處理器的響應&#xff0c;這些…

前端跨域解決方案(7):Node中間件

1 Node 中間件核心 1.1 為什么開發環境需要 Node 代理&#xff1f; 在前端開發中&#xff0c;我們常遇到&#xff1a;前端運行在localhost:3000&#xff0c;后端 API 在localhost:4000&#xff0c;跨域導致請求失敗。而傳統解決方案有以下局限性&#xff1a; 修改后端 CORS 配…

iwebsec靶場-文件上傳漏洞

01-前端JS過濾繞過 1&#xff0c;查看前端代碼對文件上傳的限制策略 function checkFile() { var file document.getElementsByName(upfile)[0].value; if (file null || file "") { alert("你還沒有選擇任何文件&a…

GitHub 趨勢日報 (2025年06月23日)

&#x1f4ca; 由 TrendForge 系統生成 | &#x1f310; https://trendforge.devlive.org/ &#x1f310; 本日報中的項目描述已自動翻譯為中文 &#x1f4c8; 今日獲星趨勢圖 今日獲星趨勢圖 390 suna 387 system-prompts-and-models-of-ai-tools 383 Web-Dev-For-Beginners…

告別水印煩惱,一鍵解鎖高清無痕圖片與視頻!

在這個數字化飛速發展的時代&#xff0c;無論是設計小白還是創意達人&#xff0c;都可能遇到這樣的困擾&#xff1a;心儀的圖片或視頻因水印而大打折扣&#xff0c;創意靈感因水印而受限。別急&#xff0c;今天就為大家帶來幾款神器&#xff0c;讓你輕松告別水印煩惱&#xff0…

LangChain4j在Java企業應用中的實戰指南:構建RAG系統與智能應用-2

LangChain4j在Java企業應用中的實戰指南&#xff1a;構建RAG系統與智能應用-2 開篇&#xff1a;LangChain4j框架及其在Java生態中的定位 隨著人工智能技術的快速發展&#xff0c;尤其是大語言模型&#xff08;Large Language Models, LLMs&#xff09;的廣泛應用&#xff0c;…