Catch2

框架

catchorg/Catch2

现代 C++ 测试框架,支持单元测试、TDD、BDD 和微基准测试。

项目简介

Catch2 是一个 C++ 测试框架,以简洁自然的测试编写方式著称,支持段式共享设置/清理、BDD 宏和基础的微基准测试功能。无需外部依赖,可作为单头文件或编译库使用。

README 预览

\n\n\n[](https://github.com/catchorg/catch2/releases)\n[](https://github.com/catchorg/Catch2/actions/workflows/linux-simple-builds.yml)\n[](https://github.com/catchorg/Catch2/actions/workflows/linux-other-builds.yml)\n[](https://github.com/catchorg/Catch2/actions/workflows/mac-builds.yml)\n[](https://ci.appveyor.com/project/catchorg/catch2)\n[](https://codecov.io/gh/catchorg/Catch2)\n[](https://godbolt.org/z/EdoY15q9G)\n[](https://discord.gg/4CWS9zD)\n\n\n## What is Catch2?\n\nCatch2 is mainly a unit testing framework for C++, but it also\nprovides basic micro-benchmarking features, and simple BDD macros.\n\nCatch2's main advantage is that using it is both simple and natural.\nTest names do not have to be valid identifiers, assertions look like\nnormal C++ boolean expressions, and sections provide a nice and local way\nto share set-up and tear-down code in tests.\n\n**Example unit test**\n```cpp\n#include \n\n#include \n\nuint32_t factorial( uint32_t number ) {\n    return number \n#include \n\n#include \n\nuint64_t fibonacci(uint64_t number) {\n    return number < 2 ? number : fibonacci(number - 1) + fibonacci(number - 2);\n}\n\nTEST_CASE("Benchmark Fibonacci", "[!benchmark]") {\n    REQUIRE(fibonacci(5) == 5);\n\n    REQUIRE(fibonacci(20) == 6'765);\n    BENCHMARK("fibonacci 20") {\n        return fibonacci(20);\n    };\n\n    REQUIRE(fibonacci(25) == 75'025);\n    BENCHMARK("fibonacci 25") {\n        return fibonacci(25);\n    };\n}\n```\n\n_Note that benchmarks are not run by default, so you need to run it explicitly\nwith the `[!benchmark]` tag._\n\n\n## Catch2 v3 has been released!\n\nYou are on the `devel` branch, where the v3 version is being developed.\nv3 brings a bunch of significant changes, the big one being that Catch2\nis no longer a single-header library. Catch2 now behaves as a normal\nlibrary, with multiple headers and separately compiled implementation.\n\nThe documentation is slowly being updated to take these changes into\naccount, but this work

常见问题 (5)

故障排除
如何修复 Catch2 v3.16.0 因错误的 _MSVC_VER 宏导致在 MSVC 下未重新启用优化的问题?

在 Catch2 合并头文件(例如 catch_amalgamated.hpp)中,转到第 1523 行,在用于重新启用优化的 pragma 的预处理器检查中,将错误的宏 _MSVC_VER 替换为 _MSC_VER。然后重新构建你的项目。示例更正:将 #if defined(_MSVC_VER) 改为 #if defined(_MSC_VER)。此问题是在提交 45f9ea1e798c2e128dcba53602ccbddfe5676f6f 中引入的;请在有补丁版本可用时使用该版本,或保留本地头文件修复作为临时解决方案。

来源 Issue #3211
故障排除
如何仅在通过 CTest 运行失败的测试时打印额外的 Catch2 诊断输出?

使用 Catch2 事件监听器,而不是将 INFO()/WARN() 与 -s 搭配使用。将诊断信息存储在全局变量或线程安全的单例中,然后仅当测试失败时,才在 testCaseEnded() 中将它们写入 stderr。CTest 的 --output-on-failure 会显示该 stderr 输出。

#include <catch2/catch_test_macros.hpp>
#include <catch2/reporters/catch_reporter_event_listener.hpp>
#include <catch2/reporters/catch_reporter_registrars.hpp>

#include <iostream>
#include <mutex>
#include <sstream>
#include <string>
#include <vector>

std::mutex g_failureInfoMutex;
std::vector<std::string> g_failureInfo;

#define FAIL_INFO(expr)                                      \
    do {                                                     \
        std::ostringstream oss;                              \
        oss << expr;                                         \
        std::lock_guard<std::mutex> lock(g_failureInfoMutex); \
        g_failureInfo.push_back(oss.str());                  \
    } while (false)

class FailureInfoListener : public Catch::EventListenerBase {
public:
    using EventListenerBase::EventListenerBase;

    void testCaseStarting(Catch::TestCaseInfo const&) override {
        std::lock_guard<std::mutex> lock(g_failureInfoMutex);
        g_failureInfo.clear();
    }

    void testCaseEnded(Catch::TestCaseStats const& stats) override {
        if (stats.totals.assertions.allOk()) {
            return;
        }

        std::cerr << "Additional failure information:\n";

        std::lock_guard<std::mutex> lock(g_failureInfoMutex);
        for (auto const& line : g_failureInfo) {
            std::cerr << line << '\n';
        }
    }
};

CATCH_REGISTER_LISTENER(FailureInfoListener)

在测试中这样使用:

TEST_CASE("GPU test") {
    FAIL_INFO("GPU: " << gpuName);
    REQUIRE(false);
}

使用以下命令运行:

ctest --output-on-failure

Catch2 没有提供从注册表中获取监听器实例的方法,因此监听器应读取共享的全局变量。如果诊断信息可能从多个线程记录,请使用互斥锁。自定义 reporter 也是一种选择,但事件监听器是更简单的推荐方案。

来源 Issue #3183
故障排除
如何在 Catch2 的 catch_discover_tests TEST_PREFIX 中保留尾随空格?

在 Catch2 v2.13.4 与 CMake v3.10.3 中,当通过 add_custom_command() 传递 TEST_PREFIX 时,末尾的空格会丢失。编辑你的构建所使用的 Catch.cmake(通常为 contrib/Catch.cmake,约第 160 行),并将:

-D "TEST_PREFIX=${_TEST_PREFIX}"

替换为:

-D "TEST_PREFIX='${_TEST_PREFIX}'"

等价形式为:

-D TEST_PREFIX='${_TEST_PREFIX}'

在 add_custom_command() 调用中保留 VERBATIM。重新配置并重新构建,以便测试发现脚本重新生成:

cmake -S . -B build
cmake --build build
ctest --test-dir build -N

通过此更改,TEST_PREFIX "${TARGET} " 会生成诸如 <target> <test name> 这样的 CTest 名称,而不是 <target><test name>。如果无法修补 Catch.cmake,可使用非空格分隔符(如 ${TARGET}. 或 ${TARGET}:)作为临时替代方案。

来源 Issue #2149
故障排除
如何修复使用 Clang 20 时 Catch2 构建失败的问题:'-Wunreachable-code-return' 和 'no matching function for call to get_wrapper'?

将 Catch2 升级到 v3.9.1 或更高版本,其中包含了 Clang 20 的构建修复。对于 Git 检出,运行:

git fetch --tags
git checkout v3.9.1
CXX=clang++ cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build

如果你只需要 Catch2 库而不需要其自测试,可以禁用开发构建作为变通方法:

CXX=clang++ cmake -S . -B build -DCATCH_DEVELOPMENT_BUILD=OFF
cmake --build build

这些失败发生在开发/自测试目标中,因此使用 CATCH_DEVELOPMENT_BUILD=OFF 构建可避免编译那些失败的测试文件。使用 -Wno-error=unreachable-code-return 只能抑制第一个警告,并不能解决 get_wrapper 模板错误。

来源 Issue #2991
故障排除
如何修复在 macOS 或 Alpine 上使用 TEMPLATE_PRODUCT_TEST_CASE 时出现的 Catch2 "no matching function for call to 'get_wrapper'" 错误?

这是由 Clang 20/21 搭配 libc++ 导致的,而不是你的测试语法问题。Clang 会拒绝接受具有不同数量模板参数的类型列表的 TEMPLATE_PRODUCT_TEST_CASE;Clang 22 修复了该编译器问题,而 Catch2 PR #3173 添加了相应的变通方案。

修复方法是将 Catch2 从 3.15.0 升级到包含 PR #3173 的更新的 v3.x 版本,或升级到最新的 v3.x 版本。对于 Meson 子项目,请更新 subprojects/catch2.wrap 并运行:

meson subprojects update catch2
meson setup --reconfigure build

对于 CMake FetchContent,请将 GIT_TAG 更新为最新的 Catch2 v3.x 版本并重新配置。

其他变通方案:
- 将编译器升级到 Clang 22。
- 如果暂时无法升级 Catch2,可以 cherry-pick 或向后移植 catchorg/Catch2 PR #3173 中的更改。

来源 Issue #3115