开发者

C++ gtest单元测试的实现示例

目录
  • 1. 单元测试
    • 1.1. 单元测试介绍
      • 1.1.1. 为什么需要单元测试
      • 1.1.2. 单元测试的类型
      • 1.1.3. 常用的C++单元测试框架
      • 1.1.4. 单元测试的实施步骤
      • 1.1.5. 单元测试的最佳实践
    • 1.2. 安装Google Test
      • 1.3. 编写代码
        • 1.3.1. CMath
        • 1.3.2. src/main.cpp
        • 1.3.3. test/main.cpp
      • 1.4. CMakeLists.txt
        • 1.5. 编译
          • 1.6. 运行单元测试
            • 1.6.1. 直接运行 runUnitTests.exe
            • 1.6.2. 运行 CTest
            • 1.6.3. visual studio code 中用插件进行单元测试

        1. 单元测试

        单元测试是软件开发过程中的一种测试方法,用于验证程序中的最小可测单元,通常是方法、类和模块等。它的目的是确保每个单元都能正确执行其预定义的功能,并且其他功能单元之间的交互符合预期。

        1.1. 单元测试介绍

        1.1.1. 为什么需要单元测试

        • 早期发现问题:在软件开发的早期阶段发现潜在的问题和错误,避免后续开发过程中的不必要的麻烦。
        • 提高代码质量:有助于提高代码质量,减少bug,增强代码可维护性。
        • 提高开发效率:支持重构和修改,提高开发效率。

        1.1.2. 单元测试的类型

        • 静态测试:在不执行程序的情况下对代码进行分析和检查的方法,包括代码审查、代码走查和静态分析工具的使用。
        • 动态测试:通过执行程序并观察其行为来测试软件的过程,包括白盒测试和黑盒测试。

        1.1.3. 常用的C++单元测试框架

        • Google Test:由Google开发,支持多种测试模式,如测试夹具、参数化测试等,并且具有良好的跨平台特性。
        • Catch2:一个轻量级的测试框架,支持行为驱动开发(BDD)风格的测试。
        • Boost.Test:Boost库的一部分,功能强大且灵活,适合大型项目的测试。
        • CppUnit:类似于JUnit的框架,适用于C++。

        1.1.4. 单元测试的实施步骤

        1. 编写测试用例:根据需求编写测试用例,模拟各种输入情况,验证函数的输出是否符合预期。
        2. 运行测试:使用测试框架提供的工具运行测试用例,观察测试结果。
        3. 分析结果:如果测试通过,说明代码在这些情况下工作正常;如果失败,则需要调试和修复。

        1.1.5. 单元测试的最佳实践

        • 早期介入:在软件开发的早期阶段就开始编写测试用例。
        • 持续集成:结合持续集成工具,在每次代码提交后自动执行测试。
        • 编写清晰的测试用例:测试用例应该尽量简单明了,避免复杂的逻辑。

        本文将介绍Google Test框dHppOgJc架的基本使用方法,包括安装、配置、编写测试用例和运行测试等步骤。

        1.2. 安装Google Test

        vcpkg install gtest
        

        1.3. 编写代码

        我们的代码目录结构如下:

        C:.
        |   CMakeLists.txt
        |   output.txt
        |   run.ps1
        |   tests_output.txt
        |
        +---.vscode
        |       c_cpp_properties.json
        |       setti编程客栈ngs.json
        |
        +---include
        |       CMath.h
        |       common.h
        |
        +---lib
        |       bay.lib
        |
        +---src
        |       CMath.cpp
        |       main.cpp
        |
        \---test
                main.cpp
        

        1.3.1. CMath

        我们写一个最简单的加法函数:

        int CMath::add(int a, int b)
        {
            return a + b;
        }
        

        1.3.2. src/main.cpp

        这是咱们正常软件的入口函数,我们在这里调用CMath的add函数:

        #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

        这是我们的单元测试代码,我们在这里调用CMath的add函数,并且使用Google Test提供的断言来验证结果:

        #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); //单元测试结果会报错
        }
        
        
        int main(int argc, char **argv) {
            ::testing::InitGoogleTest(&argc, argv);
            return RUN_ALL_TESTS();
        }
        

        1.4. CMakeLists.txt

        我们使用CMake来构建我们的项目,将生成可执行文件demo.exe和单元测试可执行文件runUnitTests.exe。

        特别注意:

        1. 在生成runUnitTests.exe时,需要包含test/.cpp 和 src/.cpp ,同时排除掉src/main.cpp,否则会报错。
        2. 建议在test/main.cpp 中使用main(),这样链接时用GTest::gtest,而不要用GTest::gtest_main,否则会报错。

        CMakeLists.txt如下:

        # 指定CMake的最低版本要求
        cmake_minimum_required(VERSION 3.10)
        
        # 设置项目名称和语言
        project(demo LANGUAGES CXX)
        
        # 设置C++标准为C++17
        set(CMAKE_CXX_STANDARD 17)
        set(CMAKE_CXX_STANDARD_REQUIRED ON) # 强制要求使用指定的C++标准
        
        # 查找外部依赖包 fmt 和 spdlog
        find_package(fmt CONFIG REQUIRED)
        find_package(spdlog CONFIG REQUIRED)
        
        # 递归查找src目录下所有的cpp源文件,作为主程序源文件
        file(GLOB_RECURSE SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp")
        
        #创建主程序可执行文件
        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文件,供测试用例复用
        file(GLOB_RECURSE UNIT_TEST_SRC_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp")
        list(FILTER UNIT_TEST_SRC_SOURCES EXCLUDE REGEX "src/main.cpp")
        # 创建测试可执行文件 runUnitTests
        add_executable(runUnitTests ${UNIT_TEST_SOURCES} ${UNIT_TEST_SRC_SOURCES})
        
        # 查找GTest库
        find_package(GTest CONFIG REQUIRED)
        # 链接GTest和GMock库到测试可执行文件
        # 注意:这里只需链接gtest和gmock,不要链接gtest_main/gmock_main,否则main函数会冲突
        target_link_lib编程raries(runUnitTests PRIVATE GTest::gtest  GTest::gmock )
        
        # 添加CTest测试
        add_test(AllTestsInMain runUnitTests)
        
        # 包含 GoogleTest 模块,自动发现并添加测试
        include(GoogleTest)
        gtest_discover_tests(runUnitTests)
        
        # 设置主程序包含目录
        # PRIVATE表示这些包含目录仅在当前目标内部可见
        # include/bay目录如不存在可去除
        # 下面两处都可根据实际情况调整
        
        # 主程序包含目录
        target_include_directories(${PROJECT_NAME} PRIVATE 
                "${CMAKE_CURRENT_SOURCE_DIR}/include"
                )
        # 测试程序包含目录
        target_include_directories(runUnitTests PRIVATE 
                "${CMAKE_CURRENT_SOURCE_DIR}/include"
                )
        
        # 链接外部依赖库到主程序
        # PRIVATE表示依赖不会传递给链接此目标的其他目标
        # 如lib/bay.lib不存在可去除
        # fmt和spdlog为必需
        
        target_link_libraries(${PROJECT_NAME} PRIVATE 
            fmt::fmt            # 格式化库
            spdlog::spdlog      # 日志库
        )
        
        target_link_libraries(runUnitTests PRIVATE 
            fmt::fmt            # 格式化库
            spdljsog::spdlog      # 日志库
        )
        

        1.5. 编译

        # 生成构建目录并配置CMake工程
        cmake -B build -S . -DCMAKE_TOOLCHAIN_FILE="${VCPKG_ROOTDIR}/scripts/buildsystems/vcpkg.cmake" 
        
        # 编译工程,若成功则运行生成的可执行文件
        cmake --build build ; 
        

        1.6. 运行单元测试

        有以下方式可以进行单元测试

        1.6.1. 直接运行 runUnitTests.exe

        输出结果如下:

        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
        

        有一条测试用例失败,是因为为我们特意在test/main.cpp中将输出结果设置错误。

        1.6.2. 运行 CTest

        cd build
        ctest
        # 也可采用 ctest -V  ,这样输出的结果会包含详细信息
        

        输出结果如下:

        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 中用插件进行单元测试

        先安装插件

        C++ gtest单元测试的实现示例

        然后点www.devze.com击插件中的单元测试,点击相关测试用例,运行即可。

        C++ gtest单元测试的实现示例

        到此这篇关于C++ gtest单元测试的实现示例的文章就介绍到这了,更多相关C++ gtest单元测试内容请搜索编程客栈(www.devze.com)以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程客栈(www.devze.com)! 

        0

        上一篇:

        下一篇:

        精彩评论

        暂无评论...
        验证码 换一张
        取 消

        最新开发

        开发排行榜