0


使用CMake和Catch2进行单元测试

前言

单元测试是软件开发过程中的重要部分,它帮助我们确保每个组件按预期工作。C++ 中进行单元测试的一个流行选择是 Catch2 测试框架,结合 CMake 构建系统,可以创建一个强大且灵活的测试环境。在这篇博客中,将演示使用 Catch2 集成到 CMake 的 CTest 工具中进行单元测试。

环境准备

  • CMake:v3.28
  • Catch 2:v3.6.0 假设目录结构如下:
MyProject/
|-- CMakeLists.txt
|-- src/
    |-- main.cpp
|-- test/
    |-- CMakeLists.txt
    |-- test.cpp

CMake 配置

根目录

CMakeLists.txt

# CMakeLists.txt
cmake_minimum_required(VERSION 3.28)  
...
option(ENABLE_TESTS "Build the test" ON)
...
if (ENABLE_TESTS)
    # 启用测试
    enable_testing()  
    add_subdirectory(test)  
endif ()

使用

enable_testing()

启用 CTest 测试。

test

目录下的

CMakeLists.txt

# test/CMakeLists.txt
include(FetchContent)  
FetchContent_Declare(  
        Catch2  
        GIT_REPOSITORY https://github.com/catchorg/Catch2.git  
        GIT_TAG        v3.6.0  
)  
FetchContent_MakeAvailable(Catch2)  
  
add_executable(SimZipTest test.cpp)  
target_link_libraries(SimZipTest PRIVATE SimZip Catch2::Catch2WithMain)  
  
add_test(NAME SimZipTest  
        COMMAND $<TARGET_FILE:SimZipTest> --success  
)  

这里使用了 CMake 的

FetchContent

方式集成 Catch2,并指定了 Git tag 为

v3.6.0

,然后使用

target_link_libraries()

将需要链接的库和 Catch 的库链接上。

Catch 2 有两种方式:

Catch2::Catch2

Catch2::Catch2WithMain

。如果不需要自定义 main 函数,则使用后者。如果需要自定义 main,则应该只链接

Catch2::Catch2

之后便是

add_test()

命令添加测试。

注意,这里使用了

--success

选项传递给单元测试的可执行文件,用于显示 Catch 2的输出。

编写测试代码

test

目录下,编写

test.cpp

代码:

// test.cpp#include"../SimZip.h"#include<catch2/catch_test_macros.hpp>#include<fstream>#include<filesystem>voidgenerateData(){  
    std::ofstream file("data.txt");if(file.is_open()){for(auto i =0; i <10; i++){ file <<"this is data for test.";}  
        file.close();}}TEST_CASE("create zip","[create_zip]"){generateData();  
    SimZip zip("test.zip", SimZip::OpenMode::Create);REQUIRE(zip.add("data.txt")==true);REQUIRE(zip.add("data.txt","folder/rename.txt")==true);REQUIRE(zip.add("empty.txt")==false);  
    zip.save();}TEST_CASE("extract zip","[extract_zip]"){  
    SimZip zip("test.zip", SimZip::OpenMode::Read);SECTION("Extract single file from zip"){  
        zip.extract("data.txt","output/");REQUIRE(fs::exists("output/data.txt"));}SECTION("Extract all files from zip"){        zip.extractall("output/");  
        std::vector<std::string> expected_files ={"data.txt","folder/rename.txt"};for(constauto& file: expected_files){REQUIRE(fs::exists("output/"+ file));}}}

在 Catch2 测试框架中,

TEST_CASE

是一个宏,用于定义一个测试用例。这个宏接受几个参数,其中最常见的是测试用例的名称和可选的标签。

TEST_CASE("test name","[tags]"){// 测试代码 }
  1. 测试用例名称:第一个参数是测试用例的名称,它是一个描述性的字符串,表明测试用例的目的或测试的行为。在 Catch2 中运行测试时,这个名称会被用来识别和过滤特定的测试。
  2. 标签:第二个参数是可选的,它允许你为测试用例添加标签。标签通常用方括号 [] 包围,并可以用逗号 , 分隔,从而为测试用例分配多个标签。标签可以用来对测试进行分类,或者在运行测试时进行过滤。
SECTION

是一个宏,用于将一个测试案例(

TEST_CASE

)划分为多个独立的部分,每个部分都可以单独运行或独立地进行断言检查。这允许你以模块化的方式编写测试,并且可以针对相同的测试设置运行多个不同的测试场景。

运行测试

使用命令:

cmake -B build
cmake --build build
ctest --test-dir build/

然后就可以看到测试结果:

$ ctest
Test project /mnt/f/Code/CppProjects/SimZip/build
    Start 1: SimZipTest
1/1 Test #1: SimZipTest .......................   Passed    0.06 sec100% tests passed, 0 tests failed out of 1

Total Test time(real)=0.10 sec

对 CTest 添加

-V

参数,可以看到详细信息

ctest --test-dir build/ -V

如果你使用的是 CLion,那么可以很方便地进行测试,选择 CTest 然后运行,即可执行测试。

测试结果:

Clion CTest运行截图

总结

CMake 和 Catch2 的结合提供了一个简单而强大的单元测试解决方案,它可以帮助你确保代码的质量。通过遵循上述步骤,你可以轻松地在你的 C++ 项目中集成测试,并保持代码的可维护性和健壮性。

标签: 单元测试

本文转载自: https://blog.csdn.net/no_say_you_know/article/details/139104506
版权归原作者 L-Super 所有, 如有侵权,请联系我们删除。

“使用CMake和Catch2进行单元测试”的评论:

还没有评论