Catch2 开源生态实践指南:为什么开源项目都选择它,以及如何将测试框架接入你的开源项目
【免费下载链接】Catch2A modern, C++-native, test framework for unit-tests, TDD and BDD - using C++14, C++17 and later (C++11 support is in v2.x branch, and C++03 on the Catch1.x branch)项目地址: https://gitcode.com/GitHub_Trending/ca/Catch2
本指南以 Catch2 仓库官方文档 docs/opensource-users.md 为主体,系统梳理 Catch2 面向开源场景的核心设计(宽松许可证、零依赖、双文件分发),列出当前仓库记录的真实使用案例(从 header-only 库、数据库引擎到游戏与音频工具),并基于仓库源码与 CMake 配置,给出接入开源项目的完整实操路径,帮助你理解"为何开源项目愿意把测试交给 Catch2"以及"如何在自己的开源项目中复用它"。
为什么 Catch2 天然适合开源项目
官方文档开篇即给出结论:Catch2 非常适合开源项目。这不是营销话术,而是由仓库内可验证的三个客观事实支撑的:
- 许可证宽松:Catch2 采用 Boost Software License 1.0(BSL-1.0)。该许可证允许自由使用、复制、修改、分发和商用,唯一要求是保留版权声明。对于希望在源码、文档与衍生作品中嵌入测试框架的开源项目而言,这是几乎无负担的许可证条款。
- 无额外依赖:Catch2 只依赖 C++ 标准库与编译器,不需要安装 Boost、Qt 等第三方运行时,降低了下游用户的构建门槛。
- 支持"双文件"分发:仓库的 extras/catch_amalgamated.hpp 与 extras/catch_amalgamated.cpp 是官方提供的合并(amalgamated)版本,仅两个文件即可携带完整测试框架,可像普通源文件一样直接加入任何构建系统。生成逻辑位于 tools/scripts/generateAmalgamatedFiles.py,它从 src/catch2/catch_all.hpp 出发将全部头文件与实现拼接而成。
官方文档同时明确了两点治理规则:该列表按字母序排列以避免暗示项目重要性排序;且只允许项目维护者或获得维护者明确同意的人添加条目,保证了列表的真实性。
使用 Catch2 的开源项目全景
以下项目名单完整继承自官方文档,并按原文结构分为"Libraries & Frameworks"与"Applications & Tools"两类。这些案例覆盖了 C++ 生态中极具代表性的领域,从中可以直观看出 Catch2 在开源世界中的广泛适用性。
Libraries & Frameworks(库与框架)
| 项目 | 简介 | 与 Catch2 生态的关联 |
|---|---|---|
| accessorpp | 用于实现属性与数据绑定的 C++ 库 | — |
| alpaka | header-only 的 C++14 加速器开发抽象库 | 其姊妹项目 LLAMA 同样在列表中 |
| ApprovalTests.cpp | C++11 实现的 Approval Tests,用于快速便捷地测试遗留代码 | 测试方法论互补 |
| args | 简单的 header-only C++ 命令行参数解析库 | — |
| Azmq | 面向 ZeroMQ 的 Boost Asio 风格绑定 | — |
| Cataclysm: Dark Days Ahead | 后启示录生存 RPG | 游戏场景 |
| ChaiScript | header-only 的嵌入式脚本语言,直接面向 C++ | 解析器/解释器场景 |
| ChakraCore | 驱动 Microsoft Edge 的 Chakra JavaScript 引擎核心 | 大型底层引擎场景 |
| Clara | 单头文件、类型安全、可打印格式化用法说明的命令行解析器 | 注意:Clara 由 Catch2 作者 Phil Nash 开发,且其代码已并入本仓库的 third_party/clara.hpp,Catch2 自身的命令行解析即基于它 |
| Couchbase-lite-core | Couchbase Lite 的下一代核心存储与查询引擎 | 移动数据库场景 |
| cppcodec | header-only C++11 编码/解码库(base64/base32/base16 等,RFC 4648) | 编解码场景 |
| DtCraft | 高性能集群计算引擎 | 分布式场景 |
| eventpp | C++ 事件库(回调、事件分发器、事件队列,信号槽/发布订阅/观察者模式) | 与 accessorpp 同作者 |
| forest | 树形数据结构模板库 | 数据结构库场景 |
| Fuxedo | 类 Oracle Tuxedo 的开源 XATMI 中间件(C/C++) | 中间件场景 |
| HIP CPU Runtime | 允许 CPU 直接执行未修改 HIP 代码的 header-only 库 | 异构计算场景 |
| Inja | 现代 C++ 的 header-only 模板引擎 | 模板引擎场景 |
| LLAMA | C++17 模板 header-only 库,抽象内存访问模式 | 与 alpaka 同属加速器生态 |
| libcluon | C++14 单头文件库,通过 UDP/TCP/共享内存粘合分布式组件,原生支持 Protobuf、LCM/ZCM、MsgPack、JSON | 分布式中间件场景 |
| MNMLSTC Core | 小而易用的 C++11 库,提供 C++14 及以后的部分功能集 | 兼容层库场景 |
| nanodbc | 原生 C ODBC API 的小型 C++ 封装 | 数据库访问场景 |
| Nonius | header-only 的 C++ 代码片段基准测试框架 | 注意与 Catch2 内置的 benchmark 模块 定位相似,均为 micro-benchmark 工具 |
| OpenALpp | 基于 OpenAL 的现代 OOP C++14 音频库,支持 Windows、Linux 与 web(emscripten) | 音频场景 |
| polymorphic_value | C++ 多态值类型 | 语言特性库场景 |
| Ppconsul | C++ 的 Consul 客户端库(服务发现与配置) | 云原生基础设施场景 |
| RxCpp(Reactive-Extensions) | 面向"随时间分布的值"的算法库(响应式编程) | 响应式编程场景 |
| SFML | Simple and Fast Multimedia Library | 多媒体/游戏开发场景 |
| SOCI | C++ 数据库访问库 | 数据库访问场景 |
| TextFlowCpp | 单头文件库,用于文本换行与列排版 | 同样由 Phil Nash 开发,本仓库中文本布局工具 src/catch2/internal/catch_textflow.hpp 即源于此 |
| thor | CUDA 的封装库 | GPU 计算场景 |
| toml++ | 现代 C++ 的 header-only TOML 解析与序列化库 | 配置文件场景 |
| Trompeloeil | C++14 线程安全的 header-only mock 框架 | 测试生态互补(mock + 测试框架) |
| wxWidgets | 跨平台 C++ GUI 库 | GUI 框架场景 |
| xmlwrapp | 基于 libxml2 的 C++ XML 解析库 | XML 处理场景 |
Applications & Tools(应用与工具)
| 项目 | 简介 | 场景分类 |
|---|---|---|
| App Mesh | 现代 C++ 实现的高可用云原生微服务应用管理平台 | 云原生运维 |
| ArangoDB | 原生多模型数据库(文档、图、键值) | 数据库引擎 |
| Cytopia | 基于 SDL2 自研等距渲染引擎的免费开源复古像素风城建游戏 | 游戏开发 |
| d-SEAMS | 现代 C++ 编写的开源分子动力学模拟结构分析工具套件 | 科学计算 |
| Giada | 极简、开源、跨平台的现场音乐制作音频工具 | 音频创作 |
| MAME | 最初意为 Multiple Arcade Machine Emulator(多街机模拟器) | 模拟器 |
| Newsbeuter | 面向文本终端的开源 RSS/Atom 阅读器 | 终端工具 |
| PopHead | 使用自研引擎开发的 2D 僵尸 RPG 游戏 | 游戏开发 |
| raspigcd | 树莓派上直接执行 GCODE 的低层 CLI 应用与库(仅需 RPi + Stepsticks) | 硬件/CNC |
| SpECTRE | 面向天体物理与引力物理多尺度、多物理场问题的数值代码 | 科学计算 |
| Standardese | 立志成为"下一代 Doxygen"的文档生成器 | 开发工具 |
从这份名单可以提炼出三个规律:一是header-only 库是主力军(alpaka、Inja、toml++、Trompeloeil 等约半数项目为单头文件/纯头文件设计),因为它们与 Catch2 一样追求"零依赖、易分发";二是Catch2 在测试生态中与其他库互为补充(如与 Trompeloeil 的 mock、ApprovalTests.cpp 的快照测试搭配使用);三是应用型项目从游戏引擎到科学计算、从模拟器到数据库引擎均有覆盖,说明其并不局限于某类特定项目。
结合源码看:为什么"零依赖 + 双文件"能够成立
要理解开源项目为何愿意采纳 Catch2,有必要从仓库源码验证其"低接入成本"承诺是如何实现的。
双文件分发的实现
extras/catch_amalgamated.hpp(约 1 万行)由 tools/scripts/generateAmalgamatedFiles.py 生成,脚本从src/catch2/catch_all.hpp出发收集全部#include的头文件,剥离版权注释后合并为单头文件,同时生成对应的catch_amalgamated.cpp(内含唯一实现文件,见 extras/catch_amalgamated.cpp)。因此下游项目只需:
# 将两个文件复制进自己的源码树即可使用 cp extras/catch_amalgamated.hpp extras/catch_amalgamated.cpp <你的项目目录>/随后把.cpp加入任意构建系统(Makefile、CMake、Bazel、meson 均可),再在测试文件中#include "catch_amalgamated.hpp"即可。
无依赖如何达成
从仓库结构看,Catch2 的全部源码仅位于 src/catch2/(实现)与 third_party/clara.hpp(内置命令行解析器,来自作者的另一开源项目 Clara,完全由头文件构成),不存在对外部第三方库的链接依赖;src/catch2/internal/下还包含 catch_windows_h_proxy.hpp 这类针对 Windows 平台的头文件代理,进一步规避平台头文件的直接依赖。当前版本宏 src/catch2/catch_version_macros.hpp 中记录的版本为Catch v3.15.2。
如何自带 main 入口
开源项目接入时通常需要自定义main()或让 Catch2 提供默认入口:
- 使用默认入口:CMake 中链接
Catch2::Catch2WithMain(自带 main 的静态库目标),或在编译时同时编译 src/catch2/catch_main.cpp; - 自行提供 main:链接
Catch2::Catch2并调用Catch::Session().run(argc, argv),例如:
#define CATCH_CONFIG_RUNNER #include "catch2/catch_all.hpp" int main(int argc, char* argv[]) { return Catch::Session().run(argc, argv); }Session::run()的完整实现位于 src/catch2/catch_session.cpp,它会完成命令行解析、测试过滤、reporter 初始化与用例执行的全流程。详细的两种接入方式对比可参考 docs/own-main.md 与 docs/cmake-integration.md。
在自己的开源项目中引入 Catch2 的实操方案
方式一:CMake FetchContent / add_subdirectory(推荐给源码分发项目)
如果项目本身使用 CMake,最省事的接入方式是让下游构建时直接引入 Catch2 源码。CMake 配置脚本 CMake/Catch2Config.cmake.in 会导出Catch2::Catch2与Catch2::Catch2WithMain两个目标,find_package或add_subdirectory之后即可直接链接:
find_package(Catch2 3 REQUIRED) # 或使用 add_subdirectory(...) 内嵌源码 add_executable(my_tests tests.cpp) target_link_libraries(my_tests PRIVATE Catch2::Catch2WithMain) enable_testing() include(CTest) add_test(NAME my_tests COMMAND my_tests)仓库根 CMakeLists.txt 中的可配置选项同样服务于开源接入场景,例如:
CATCH_INSTALL_DOCS(默认 ON):安装文档到CMAKE_INSTALL_DOCDIR;CATCH_INSTALL_EXTRAS(默认 ON):安装 extras/ParseAndAddCatchTests.cmake、extras/Catch.cmake、extras/CatchAddTests.cmake、extras/CatchShardTests.cmake 等辅助脚本及 gdb/lldb 调试脚本;CATCH_DEVELOPMENT_BUILD(默认 OFF):开启后才会构建 SelfTest、示例、基准与模糊测试等开发目标。
注意 CMakeLists.txt 的注释:当 Catch2 以add_subdirectory作为子项目嵌入时(NOT_SUBPROJECT为假),会跳过安装步骤以避免破坏目标路径。
方式二:双文件直拷(推荐给极简/非 CMake 项目)
对 Makefile、Bazel、meson 或手写构建脚本的项目,直接使用上文提到的catch_amalgamated.hpp/.cpp两个文件即可。这也是官方文档强调的"two file distribution"价值所在——它让 Catch2 对构建系统的假设降到最低。
方式三:直接写测试,从最小用例开始
无论采用哪种接入方式,测试代码本身写法一致:
#include <catch2/catch_test_macros.hpp> unsigned int Factorial(unsigned int number) { return number <= 1 ? number : Factorial(number - 1) * number; } TEST_CASE("Factorials are computed", "[factorial]") { REQUIRE(Factorial(1) == 1); REQUIRE(Factorial(2) == 2); REQUIRE(Factorial(10) == 3628800); }更完整的入门路径请参考 docs/tutorial.md;断言宏体系见 docs/assertions.md;BDD 风格支持见 docs/test-cases-and-sections.md。
从开源用户列表反观 Catch2 的测试生态位置
梳理这份列表还可以得到一个对开源维护者有价值的结论:Catch2 常与专门的 mock、快照测试库搭配形成完整测试栈。例如列表中的 Trompeloeil(线程安全 mock)与 ApprovalTests.cpp(遗留代码快照测试)本身也是开源项目,它们与 Catch2 是"测试框架 + 辅助工具"的关系,而非竞争关系。这意味着开源项目在技术选型时,可以把 Catch2 视为一个中立的、可自由组合的测试底座。
此外,官方文档还维护了一份平行的商业用户列表 docs/commercial-users.md,开源与商业两条线共同印证了该框架在 C++ 社区的接受度。如果你希望自己的开源项目被收录进这份名单,请记住官方的唯一规则:你必须是项目维护者,或已获得维护者的明确同意,并且按字母序插入对应分类中。
小结
围绕官方文档 docs/opensource-users.md,本文完成三件事:第一,完整继承了官方记载的 40 余个使用 Catch2 的开源项目名单,并按库/框架与应用/工具两大类整理成表;第二,从仓库源码层面验证了 Catch2 面向开源场景的三大承诺——BSL-1.0 宽松许可(见 LICENSE.txt)、零外部依赖(全部实现集中在 src/catch2/)、双文件分发(由 tools/scripts/generateAmalgamatedFiles.py 生成的 extras/catch_amalgamated.hpp 与 extras/catch_amalgamated.cpp);第三,给出了 CMake FetchContent、find_package与双文件直拷三条可立即落地的接入路径。无论你的项目是 header-only 库、数据库引擎、游戏还是科学计算工具,按文中方案即可在最小成本下获得一套现代 C++ 原生、支持 TDD 与 BDD 的测试能力。
【免费下载链接】Catch2A modern, C++-native, test framework for unit-tests, TDD and BDD - using C++14, C++17 and later (C++11 support is in v2.x branch, and C++03 on the Catch1.x branch)项目地址: https://gitcode.com/GitHub_Trending/ca/Catch2
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考