C++ 测试:框架与工具
C++ 代码质量是软件可靠性的关键因素。与具有托管内存的语言不同,C++ 中的错误可能导致严重崩溃、内存泄漏和未定义行为。单元测试系统能够在早期阶段发现缺陷,简化重构过程,并记录函数的行为。在本文中,我们将介绍三种流行的 C++ 测试框架:Google Test、Catch2 和 doctest,以及将它们集成到开发流程中的工具。
为什么需要在 C++ 中进行测试?
- 重构安全性: 测试能即时提示回归问题。
- 文档: 可读性强的测试可作为 API 使用的活示例。
- CI 集成: 每次提交时自动运行测试。
- 发现未定义行为: 结合 sanitizer(AddressSanitizer、UndefinedBehaviorSanitizer)进行测试。
1. Google Test (GTest)
来自 Google 的最流行框架。支持 xUnit 风格,拥有丰富的断言宏集、自动测试注册、模拟(通过 Google Mock)和参数化测试。
安装(通过 CMake FetchContent)
# CMakeLists.txtinclude(FetchContent)FetchContent_Declare( googletest GIT_REPOSITORY https://github.com/google/googletest.git GIT_TAG release-1.12.1)FetchContent_MakeAvailable(googletest)
add_executable(my_tests test.cpp)target_link_libraries(my_tests GTest::gtest_main)测试示例
#include <gtest/gtest.h>
int factorial(int n) { return (n <= 1) ? 1 : n * factorial(n - 1);}
TEST(FactorialTest, HandlesZeroInput) { EXPECT_EQ(factorial(0), 1);}
TEST(FactorialTest, HandlesPositiveInput) { EXPECT_EQ(factorial(5), 120); EXPECT_GT(factorial(3), 5);}
int main(int argc, char **argv) { ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS();}TEST()— 用于定义测试用例的宏。EXPECT_EQ— 相等性检查(非致命)。ASSERT_*— 致命检查(失败时终止测试)。
2. Catch2
一个现代框架,注重可读性和简洁性。支持 BDD 风格(Given-When-Then)、节(将测试划分为嵌套场景)和随机数据生成。无需继承基类。
安装(单头文件或通过 vcpkg)
# vcpkgvcpkg install catch2
# CMakefind_package(Catch2 REQUIRED)target_link_libraries(my_tests Catch2::Catch2)测试示例
#define CATCH_CONFIG_MAIN#include <catch2/catch.hpp>
int add(int a, int b) { return a + b; }
TEST_CASE("Addition works", "[math]") { REQUIRE(add(2, 2) == 4); CHECK(add(-1, 1) == 0);
SECTION("With zero") { REQUIRE(add(0, 5) == 5); }}
TEST_CASE("String concatenation", "[string]") { std::string result = std::string("Hello ") + "World"; CHECK(result == "Hello World");}TEST_CASE— 声明带有名称和标签的测试。REQUIRE— 致命检查。CHECK— 非致命检查。SECTION— 嵌套场景(每个节从共同状态开始运行)。
3. Doctest
轻量且快速的替代方案。受 Catch2 启发,但编译速度快 2-5 倍。适用于重视构建速度的项目。支持仅头文件、CHECK 和 REQUIRE 宏,以及 XML 格式输出。