c++ 单元测试框架选择 googletest和catch2哪个好

梦涛君_7403

梦涛君_7403

2026-03-19

619人浏览

原创

catch2适合快速启动,单头文件、无需链接,但仅限一个源文件定义catch_config_main;googletest更适中大型项目,支持mock、参数化等工程需求,但编译慢且需正确配置。

c++ 单元测试框架选择 googletest和catch2哪个好

项目刚起步,想写个测试但不想配环境?用 Catch2

直接 #include <catch2></catch2> 就能开测,连编译库都不用——Catch2 是单头文件设计,没有链接、没有 -lgtest、不用改 CMakeLists.txt。你写完一个 add() 函数,立刻就能在同一个文件里补上测试:

#define CATCH_CONFIG_MAIN
#include <catch2>
int add(int a, int b) { return a + b; }
TEST_CASE("add works") {
    REQUIRE(add(2, 3) == 5);
}
</catch2>

常见错误现象:有人把 #define CATCH_CONFIG_MAIN 放错位置(比如放在 #include 之后),结果链接时报 undefined reference to 'main';还有人漏掉这个宏,又没自己写 main(),程序根本跑不起来。

  • CATCH_CONFIG_MAIN 必须在任何 #include <catch2></catch2> 之前定义
  • 只允许在一个源文件里定义它(否则重复定义 main
  • 如果项目已有 main(),就用 CATCH_CONFIG_RUNNER 替代

团队在做中大型项目,要长期维护、加 Mock、跑 CI?选 GoogleTest

GoogleTest 不是“更好”,而是“更扛事”:它和 GoogleMock 天然打通,支持 TEST_F 测试夹具、INSTANTIATE_TEST_SUITE_P 参数化测试、ASSERT_DEATH 死亡测试——这些不是炫技,是真实工程里绕不开的需求。比如你要验证某个函数在非法输入下是否真的 abort,Catch2 得自己 fork + sigaction 拦截,而 GoogleTest 一行 ASSERT_DEATH(func(-1), ".*invalid.*"); 就搞定。

性能影响明显:因为重度依赖模板和宏展开,GoogleTest 编译慢,单个测试文件动辄多花 1–3 秒;但运行时开销几乎为零,CI 上稳定可靠。

  • 必须调用 ::testing::InitGoogleTest(&argc, argv),否则 RUN_ALL_TESTS() 可能静默跳过所有测试
  • 链接时漏掉 -pthread 会导致多线程测试随机 hang 住(尤其在 Linux CI 环境)
  • Windows 下若用 MSVC,记得关掉 /GL(全程序优化),否则链接时报 LNK2019

写测试时总纠结命名、语法太重?Catch2 的 BDD 风格真省心

GoogleTest 要求测试名是合法 C++ 标识符:TEST(MathTest, Add_Two_Positive_Numbers)——看着就累;Catch2 直接写自然语言:TEST_CASE("add two positive numbers"),甚至支持嵌套描述:

C++
C++

"空空如也"

下载
SCENARIO("string reversal") {
    GIVEN("a non-empty string") {
        std::string s = "hello";
        WHEN("reversed") {
            auto r = reverse(s);
            THEN("it should be 'olleh'") {
                REQUIRE(r == "olleh");
            }
        }
    }
}

这不是为了好看。BDD 结构让产品、测试、开发三方看同一份测试代码时,能对齐验收逻辑。但注意:SCENARIO/GIVEN 这些宏本质还是函数作用域,变量不能跨 WHEN 传递——有人误以为能像真实语句一样“延续上下文”,结果编译报 use of undeclared identifier

  • REQUIRE 失败立即退出当前 SECTIONWHENCHECK 则继续执行,适合检查多个独立断言
  • 别在 GIVEN 里做 heavy setup(比如读文件),它可能被多次执行(因 Catch2 的 section 重入机制)
  • 中文字符串当测试名?可以,但某些旧版终端或 CI 日志会乱码,建议仍用英文描述

已经写了部分 GoogleTest,现在想切到 Catch2?别硬切,先混用

没有“迁移工具”,也别删旧测试重写。实际做法是:新模块用 Catch2,老模块维持 GoogleTest,两个测试可共存于同一项目——只要它们的 main() 不冲突。比如用 Catch2CATCH_CONFIG_RUNNER 写个自定义入口,手动注册两套测试:

#include <catch2>
extern "C" int run_gtest_main(int, char**); // 原 gtest main 封装
int main(int argc, char* argv[]) {
    Catch::Session session;
    auto cli = session.cli();
    session.applyCommandLine(argc, argv);
    int catch_result = session.run();
    int gtest_result = run_gtest_main(argc, argv);
    return catch_result || gtest_result ? 1 : 0;
}
</catch2>

容易踩的坑:两个框架都试图接管标准输出或信号处理(比如 SIGABRT),导致死亡测试行为不一致;更稳妥的做法是分进程运行——CI 脚本里分别跑 ./test_gtest./test_catch2

真正卡住人的从来不是语法差异,而是团队对“测试失败算不算阻断发布”的共识。框架只是工具,选哪个,最终取决于你们愿不愿意为每个 if 分支补上对应测试,而不是等它在线上崩了再翻日志。

C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!

相关文章

c++速学教程(入门到精通)
c++速学教程(入门到精通)

c++怎么学习?c++怎么入门?c++在哪学?c++怎么学才快?不用担心,这里为大家提供了c++速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

c++

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
typedef和define区别
typedef和define区别

typedef和define区别在类型检查、作用范围、可读性、错误处理和内存占用等。本专题为大家提供typedef和define相关的文章、下载、课程内容,供大家免费下载体验。

2023.09.26

313

5

define的用法
define的用法

define用法:1、定义常量;2、定义函数宏:3、定义条件编译;4、定义多行宏。更多关于define的用法的内容,大家可以阅读本专题下的文章。

2023.10.11

619

5

require的用法
require的用法

require的用法有引入模块、导入类或方法、执行特定任务。想了解更多require的相关内容,可以阅读本专题下面的文章。

2023.11.27

1935

6

mysql标识符无效错误怎么解决
mysql标识符无效错误怎么解决

mysql标识符无效错误的解决办法:1、检查标识符是否被其他表或数据库使用;2、检查标识符是否包含特殊字符;3、使用引号包裹标识符;4、使用反引号包裹标识符;5、检查MySQL的配置文件等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2023.12.04

10820

5

Python标识符有哪些
Python标识符有哪些

Python标识符有变量标识符、函数标识符、类标识符、模块标识符、下划线开头的标识符、双下划线开头、双下划线结尾的标识符、整型标识符、浮点型标识符等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.02.23

943

5

java标识符合集
java标识符合集

本专题整合了java标识符相关内容,想了解更多详细内容,请阅读下面的文章。

2025.06.11

6590

9

c++标识符介绍
c++标识符介绍

本专题整合了c++标识符相关内容,阅读专题下面的文章了解更多详细内容。

2025.08.07

2602

7

js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.03

1518

5

js截取字符串的方法
js截取字符串的方法

js截取字符串的方法有substring()方法、substr()方法、slice()方法、split()方法和slice()方法。本专题为大家提供字符串相关的文章、下载、课程内容,供大家免费下载体验。

2023.09.04

2184

5

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Conan 2 Essentials 免费课程
Conan 2 Essentials 免费课程

共0课时 | 0人学习

CMake 与 Conan 集成实践
CMake 与 Conan 集成实践

共0课时 | 0人学习

Conan 2 高级依赖模型介绍
Conan 2 高级依赖模型介绍

共0课时 | 0人学习