直接链接gtest::gtest_main库而非手写main,cmake中需find_package(gtest required)并target_link_libraries(your_target gtest::gtest_main),否则因缺少入口导致静默跳过测试。

怎么在C++项目里快速跑起第一个GTest测试
能跑起来,不报链接错误,是最大门槛。很多同学卡在 main 冲突或 gtest_main 没连上。
- 别自己写
main()—— 直接链接gtest_main库,它已内置了标准入口;手写main且没调RUN_ALL_TESTS()就会静默跳过所有测试 - CMake里用
find_package(GTest REQUIRED)后,必须同时target_link_libraries(your_test_target GTest::gtest_main),只链GTest::gtest会缺main - 确保测试源文件(如
test_math.cpp)被加入构建,但不要把它们混进主可执行目标里,否则符号重复
GTest断言写法和常见误用
ASSERT_* 和 EXPECT_* 不只是“失败是否继续”的区别,还影响作用域行为——前者失败直接 return,后者继续执行本函数内后续语句。
-
ASSERT_EQ(a, b)在函数中间失败,后续代码不执行;EXPECT_EQ(a, b)失败后仍会跑下面的EXPECT_TRUE(...),适合批量检查 - 字符串比较慎用
ASSERT_STREQ:若传入nullptr,会直接崩溃(不是断言失败),应先用ASSERT_NE(ptr, nullptr) - 浮点数必须用
ASSERT_FLOAT_EQ或带误差的ASSERT_NEAR(val1, val2, abs_error),直接==比较float几乎必挂
测试夹具(Test Fixture)什么时候该用、怎么组织
当多个测试需要共用初始化/清理逻辑,且涉及非 trivial 资源(如临时文件、mock 对象、全局状态重置)时,才值得上 class XxxTest : public ::testing::Test。
- 所有
SetUp()里的对象,在每个TEST_F运行前重建;TearDown()在每个测试后调用,哪怕测试崩溃也保证执行 - 成员变量必须声明为
protected,否则子类测试无法访问;不要在构造函数里做初始化——GTest 不保证构造顺序,且可能绕过SetUp() - 避免在
SetUp()中抛异常,GTest 不捕获它,会导致整个测试程序 abort;改用ASSERT_*()做前置检查
编译与运行时容易被忽略的细节
GTest 默认关闭 RTTI 和异常,但你的项目如果开了 -fno-rtti 或 -fno-exceptions,而 GTest 库是用默认选项编译的,链接时可能符号不匹配。
立即学习“C++免费学习笔记(深入)”;
- 用
g++ -std=c++17 -pthread编译测试代码,-pthread是硬性要求,漏掉会触发未定义行为甚至死锁 - 运行时加
--gtest_filter=MySuite.MyCase可单跑某个测试;--gtest_list_tests查看所有注册名,注意命名中的点号.是分隔符,不是路径 - CI 环境中若提示
Segmentation fault (core dumped)且无堆栈,大概率是gtest_main没链接成功,或者测试二进制混用了不同 ABI 版本的 libstdc++
最麻烦的永远不是写断言,而是让测试进程干净启动、资源正确释放、错误信息指向真实位置——尤其当 SetUp() 里打开文件又忘记关,第二次测试就因 EMFILE 失败时,问题藏得最深。










