C++ gtest單元測試的實(shí)現(xiàn)示例
1. 單元測試
單元測試是軟件開發(fā)過程中的一種測試方法,用于驗(yàn)證程序中的最小可測單元,通常是方法、類和模塊等。它的目的是確保每個(gè)單元都能正確執(zhí)行其預(yù)定義的功能,并且其他功能單元之間的交互符合預(yù)期。
1.1. 單元測試介紹
1.1.1. 為什么需要單元測試
- 早期發(fā)現(xiàn)問題:在軟件開發(fā)的早期階段發(fā)現(xiàn)潛在的問題和錯(cuò)誤,避免后續(xù)開發(fā)過程中的不必要的麻煩。
- 提高代碼質(zhì)量:有助于提高代碼質(zhì)量,減少bug,增強(qiáng)代碼可維護(hù)性。
- 提高開發(fā)效率:支持重構(gòu)和修改,提高開發(fā)效率。
1.1.2. 單元測試的類型
- 靜態(tài)測試:在不執(zhí)行程序的情況下對代碼進(jìn)行分析和檢查的方法,包括代碼審查、代碼走查和靜態(tài)分析工具的使用。
- 動(dòng)態(tài)測試:通過執(zhí)行程序并觀察其行為來測試軟件的過程,包括白盒測試和黑盒測試。
1.1.3. 常用的C++單元測試框架
- Google Test:由Google開發(fā),支持多種測試模式,如測試夾具、參數(shù)化測試等,并且具有良好的跨平臺特性。
- Catch2:一個(gè)輕量級的測試框架,支持行為驅(qū)動(dòng)開發(fā)(BDD)風(fēng)格的測試。
- Boost.Test:Boost庫的一部分,功能強(qiáng)大且靈活,適合大型項(xiàng)目的測試。
- CppUnit:類似于JUnit的框架,適用于C++。
1.1.4. 單元測試的實(shí)施步驟
- 編寫測試用例:根據(jù)需求編寫測試用例,模擬各種輸入情況,驗(yàn)證函數(shù)的輸出是否符合預(yù)期。
- 運(yùn)行測試:使用測試框架提供的工具運(yùn)行測試用例,觀察測試結(jié)果。
- 分析結(jié)果:如果測試通過,說明代碼在這些情況下工作正常;如果失敗,則需要調(diào)試和修復(fù)。
1.1.5. 單元測試的最佳實(shí)踐
- 早期介入:在軟件開發(fā)的早期階段就開始編寫測試用例。
- 持續(xù)集成:結(jié)合持續(xù)集成工具,在每次代碼提交后自動(dòng)執(zhí)行測試。
- 編寫清晰的測試用例:測試用例應(yīng)該盡量簡單明了,避免復(fù)雜的邏輯。
本文將介紹Google Test框架的基本使用方法,包括安裝、配置、編寫測試用例和運(yùn)行測試等步驟。
1.2. 安裝Google Test
vcpkg install gtest
1.3. 編寫代碼
我們的代碼目錄結(jié)構(gòu)如下:
C:.
| CMakeLists.txt
| output.txt
| run.ps1
| tests_output.txt
|
+---.vscode
| c_cpp_properties.json
| settings.json
|
+---include
| CMath.h
| common.h
|
+---lib
| bay.lib
|
+---src
| CMath.cpp
| main.cpp
|
\---test
main.cpp
1.3.1. CMath
我們寫一個(gè)最簡單的加法函數(shù):
int CMath::add(int a, int b)
{
return a + b;
}
1.3.2. src/main.cpp
這是咱們正常軟件的入口函數(shù),我們在這里調(diào)用CMath的add函數(shù):
#include <iostream>
#include "CMath.h"
int main() {
CMath math;
std::cout << math.add(1,2) << std::endl;
return 0;
}
1.3.3. test/main.cpp
這是我們的單元測試代碼,我們在這里調(diào)用CMath的add函數(shù),并且使用Google Test提供的斷言來驗(yàn)證結(jié)果:
#include <gtest/gtest.h>
#include "common.h"
#include "CMath.h"
// 測試用例
TEST(AdditionTest, PositiveNumbers) {
CMath math;
EXPECT_EQ(math.add(1, 2), 3);
}
TEST(AdditionTest, NegativeNumbers) {
CMath math;
EXPECT_EQ(math.add(-1, -2), -4); //單元測試結(jié)果會報(bào)錯(cuò)
}
int main(int argc, char **argv) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
1.4. CMakeLists.txt
我們使用CMake來構(gòu)建我們的項(xiàng)目,將生成可執(zhí)行文件demo.exe和單元測試可執(zhí)行文件runUnitTests.exe。
特別注意:
- 在生成runUnitTests.exe時(shí),需要包含test/.cpp 和 src/.cpp ,同時(shí)排除掉src/main.cpp,否則會報(bào)錯(cuò)。
- 建議在test/main.cpp 中使用main(),這樣鏈接時(shí)用
GTest::gtest,而不要用GTest::gtest_main,否則會報(bào)錯(cuò)。
CMakeLists.txt如下:
# 指定CMake的最低版本要求
cmake_minimum_required(VERSION 3.10)
# 設(shè)置項(xiàng)目名稱和語言
project(demo LANGUAGES CXX)
# 設(shè)置C++標(biāo)準(zhǔn)為C++17
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON) # 強(qiáng)制要求使用指定的C++標(biāo)準(zhǔn)
# 查找外部依賴包 fmt 和 spdlog
find_package(fmt CONFIG REQUIRED)
find_package(spdlog CONFIG REQUIRED)
# 遞歸查找src目錄下所有的cpp源文件,作為主程序源文件
file(GLOB_RECURSE SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp")
#創(chuàng)建主程序可執(zhí)行文件
add_executable(${PROJECT_NAME} ${SOURCES})
# 啟用測試功能
enable_testing()
# 遞歸查找test目錄下所有的cpp文件,作為單元測試源文件
file(GLOB_RECURSE UNIT_TEST_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/test/*.cpp")
# 查找src目錄下除main.cpp外的所有cpp文件,供測試用例復(fù)用
file(GLOB_RECURSE UNIT_TEST_SRC_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp")
list(FILTER UNIT_TEST_SRC_SOURCES EXCLUDE REGEX "src/main.cpp")
# 創(chuàng)建測試可執(zhí)行文件 runUnitTests
add_executable(runUnitTests ${UNIT_TEST_SOURCES} ${UNIT_TEST_SRC_SOURCES})
# 查找GTest庫
find_package(GTest CONFIG REQUIRED)
# 鏈接GTest和GMock庫到測試可執(zhí)行文件
# 注意:這里只需鏈接gtest和gmock,不要鏈接gtest_main/gmock_main,否則main函數(shù)會沖突
target_link_libraries(runUnitTests PRIVATE GTest::gtest GTest::gmock )
# 添加CTest測試
add_test(AllTestsInMain runUnitTests)
# 包含 GoogleTest 模塊,自動(dòng)發(fā)現(xiàn)并添加測試
include(GoogleTest)
gtest_discover_tests(runUnitTests)
# 設(shè)置主程序包含目錄
# PRIVATE表示這些包含目錄僅在當(dāng)前目標(biāo)內(nèi)部可見
# include/bay目錄如不存在可去除
# 下面兩處都可根據(jù)實(shí)際情況調(diào)整
# 主程序包含目錄
target_include_directories(${PROJECT_NAME} PRIVATE
"${CMAKE_CURRENT_SOURCE_DIR}/include"
)
# 測試程序包含目錄
target_include_directories(runUnitTests PRIVATE
"${CMAKE_CURRENT_SOURCE_DIR}/include"
)
# 鏈接外部依賴庫到主程序
# PRIVATE表示依賴不會傳遞給鏈接此目標(biāo)的其他目標(biāo)
# 如lib/bay.lib不存在可去除
# fmt和spdlog為必需
target_link_libraries(${PROJECT_NAME} PRIVATE
fmt::fmt # 格式化庫
spdlog::spdlog # 日志庫
)
target_link_libraries(runUnitTests PRIVATE
fmt::fmt # 格式化庫
spdlog::spdlog # 日志庫
)
1.5. 編譯
# 生成構(gòu)建目錄并配置CMake工程
cmake -B build -S . -DCMAKE_TOOLCHAIN_FILE="${VCPKG_ROOTDIR}/scripts/buildsystems/vcpkg.cmake"
# 編譯工程,若成功則運(yùn)行生成的可執(zhí)行文件
cmake --build build ;
1.6. 運(yùn)行單元測試
有以下方式可以進(jìn)行單元測試
1.6.1. 直接運(yùn)行 runUnitTests.exe
輸出結(jié)果如下:
3
[==========] Running 2 tests from 1 test suite.
[----------] Global test environment set-up.
[----------] 2 tests from AdditionTest
[ RUN ] AdditionTest.PositiveNumbers
[ OK ] AdditionTest.PositiveNumbers (0 ms)
[ RUN ] AdditionTest.NegativeNumbers
C:\Users\Admin\05.gtest\test\main.cpp(13): error: Expected equality of these values:
math.add(-1, -2)
Which is: -3
-4
[ FAILED ] AdditionTest.NegativeNumbers (0 ms)
[----------] 2 tests from AdditionTest (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 ] AdditionTest.NegativeNumbers
1 FAILED TEST
有一條測試用例失敗,是因?yàn)闉槲覀兲匾庠趖est/main.cpp中將輸出結(jié)果設(shè)置錯(cuò)誤。
1.6.2. 運(yùn)行 CTest
cd build ctest # 也可采用 ctest -V ,這樣輸出的結(jié)果會包含詳細(xì)信息
輸出結(jié)果如下:
Test project C:/Users/Admin/05.gtest/build
Start 1: AdditionTest.PositiveNumbers
1/3 Test #1: AdditionTest.PositiveNumbers ..... Passed 0.09 sec
Start 2: AdditionTest.NegativeNumbers
2/3 Test #2: AdditionTest.NegativeNumbers .....***Failed 0.01 sec
Start 3: AllTestsInMain
3/3 Test #3: AllTestsInMain ...................***Failed 0.01 sec
33% tests passed, 2 tests failed out of 3
Total Test time (real) = 0.13 sec
The following tests FAILED:
2 - AdditionTest.NegativeNumbers (Failed)
3 - AllTestsInMain (Failed)
Errors while running CTest
1.6.3. visual studio code 中用插件進(jìn)行單元測試
先安裝插件

然后點(diǎn)擊插件中的單元測試,點(diǎn)擊相關(guān)測試用例,運(yùn)行即可。

到此這篇關(guān)于C++ gtest單元測試的實(shí)現(xiàn)示例的文章就介紹到這了,更多相關(guān)C++ gtest單元測試內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
OpenCV實(shí)現(xiàn)低對比度圖像臟污區(qū)域檢測
本文主要介紹了OpenCV實(shí)現(xiàn)低對比度圖像臟污區(qū)域檢測,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-09-09
Java C++ 算法題解leetcode1582二進(jìn)制矩陣特殊位置
這篇文章主要為大家介紹了Java C++ 算法題解leetcode1582二進(jìn)制矩陣特殊位置示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-09-09
C語言中isdigit()函數(shù)和isxdigit()函數(shù)的用法
這篇文章主要介紹了C語言中isdigit()函數(shù)和isxdigit()函數(shù)的用法,用來判斷字符師傅為阿拉伯?dāng)?shù)字和16進(jìn)制數(shù)字,需要的朋友可以參考下2015-08-08
C++模擬實(shí)現(xiàn)stack和Queue的操作示例
這篇文章主要介紹了C++模擬實(shí)現(xiàn)stack和Queue的操作示例,文中通過代碼示例給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下2024-06-06
C++實(shí)現(xiàn)四則運(yùn)算器(帶括號)
這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)四則運(yùn)算器,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-11-11

