C++ 测试:代码验证的框架与工具

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

C++ 测试:框架与工具概述



测试是专业 C++ 开发中不可或缺的一部分。与动态类型语言不同,C++ 需要特别关注内存管理、RAII 和模板元编程。没有高质量的测试,即使是小的重构也可能导致难以发现的错误。在本文中,我们将介绍 C++ 中用于单元测试的主要框架、它们的特点以及使用示例。



为什么要测试 C++ 代码?

引入测试的主要原因:

  • 重构的安全性 — 测试在更改之前锁定正确的行为。
  • 文档 — 测试展示了如何使用 API。
  • 回归检测 — 每次提交后自动检查。
  • 边界情况验证 — 处理 nullptr、空容器、溢出等。


流行的 C++ 框架



1. Google Test (gtest)

来自 Google 的最常用框架。支持自动测试注册、ASSERT_* 和 EXPECT_* 宏、参数化测试、通过 Google Mock 进行模拟。

#include <gtest/gtest.h>

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

TEST(AdditionTest, PositiveNumbers) { EXPECT_EQ(add(2, 3), 5); EXPECT_EQ(add(0, 0), 0);}

TEST(AdditionTest, NegativeNumbers) { EXPECT_EQ(add(-1, -2), -3);}

int main(int argc, char **argv) { ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS();}

特点:

  • 支持死亡测试以验证 assert。
  • 模拟工厂 (gmock) 用于隔离依赖。
  • 与 CMake 集成 (find_package(GTest))。


2. Catch2

具有表达性语法的现代框架。无需单独注册测试 — 只需 TEST_CASE 宏。支持 BDD 风格 (Given-When-Then)。

#include <catch2/catch_test_macros.hpp>

int factorial(int n) { return n <= 1 ? 1 : n * factorial(n - 1);}

TEST_CASE("Factorials are computed", "[math]") { REQUIRE(factorial(0) == 1); REQUIRE(factorial(1) == 1); REQUIRE(factorial(5) == 120);}

TEST_CASE("Negative input", "[math][edge]") { REQUIRE_THROWS_AS(factorial(-1), std::domain_error);}

特点:

  • 测试数据生成 (GENERATE)。
  • 将测试划分为节 (SECTION)。
  • 自动选择 main() (如果定义了 CATCH_CONFIG_MAIN)。


3. doctest

轻量级且快速的框架,编译时间最短。非常适合注重构建速度的项目。语法类似于 Catch2。

#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN#include <doctest/doctest.h>

int divide(int a, int b) { if (b == 0) throw std::invalid_argument("division by zero"); return a / b;}

TEST_CASE("Division") { CHECK(divide(10, 2) == 5); CHECK_THROWS_AS(divide(5, 0), std::invalid_argument);}

特点:

  • 非常快速的编译 (头文件约 5 KB)。
  • 支持 CHECK、REQUIRE、WARN 宏。
  • 内置 XML/JSON 报告器。


4. Boost.Test

Boost 库的一部分。功能丰富,但需要更多样板代码。支持自动和手动测试注册。

#define BOOST_TEST_MODULE MyTest#include <boost/test/included/unit_test.hpp>

BOOST_AUTO_TEST_SUITE(MathTests)

BOOST_AUTO_TEST_CASE(TestSum) { BOOST_CHECK_EQUAL(2 + 2, 4); BOOST_CHECK_CLOSE(3.14159, 3.14, 0.1); // 精度 0.1%}

BOOST_AUTO_TEST_CASE(TestFail) { BOOST_REQUIRE_MESSAGE(false, "This test always fails");}

BOOST_AUTO_TEST_SU

推荐