
gtest 的 ASSERT_* 和 EXPECT_* 有什么区别?
核心区别在失败时的行为:ASSERT_* 是“硬中断”,一旦断言失败,当前测试函数立刻返回,后续语句不执行;EXPECT_* 是“软提示”,失败只记录错误,测试函数继续运行。比如你在验证对象初始化后调用多个成员函数,用 EXPECT_EQ 能一次性看到所有失败点;但若 ptr 为 nullptr 就不该继续解引用,这时该用 ASSERT_NE(ptr, nullptr)。
常见组合习惯:
- 用
ASSERT_*做前置条件检查(如指针非空、文件打开成功) - 用
EXPECT_*做主体逻辑验证(如计算结果、状态值) - 避免在循环体内滥用
ASSERT_*,否则可能漏掉后续迭代的错误
如何写一个最简可运行的 gtest 测试用例?
不需要宏定义或复杂配置,只要包含头文件、写 TEST 宏、链接 libgtest 即可运行。注意:gtest 不依赖 main(),它自己提供,所以你的测试文件里不要写自己的 main。
#includeTEST(MathTest, AddPositiveNumbers) { EXPECT_EQ(2 + 3, 5); EXPECT_GT(10, 7); }
int main(int argc, char **argv) { ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); }
编译命令示例(假设已安装 gtest):
立即学习“C++免费学习笔记(深入)”;
- g++ -std=c++11 test.cpp -lgtest -lgtest_main -pthread
- 确保链接
-lgtest_main,它提供了默认main;如果自己写了main,就只链-lgtest - 缺少
-pthread可能导致 segfault 或静默失败
字符串比较出错时为什么 EXPECT_EQ 报错信息看不懂?
EXPECT_EQ 对 const char* 默认做指针比较,不是内容比较。比如 EXPECT_EQ("hello", "hello") 实际比较两个字符串字面量的地址,结果是 false —— 这不是你想要的。
正确做法:
- 用
EXPECT_STREQ("hello", str.c_str())比较 C 风格字符串 - 用
EXPECT_EQ(std::string("hello"), str)或EXPECT_EQ("hello"s, str)(C++14 字符串字面量)让类型推导走std::string的重载 - 对
std::string成员直接用EXPECT_EQ是安全的,因为有对应重载
错误示例触发的报错类似:Expected: "abc" Which is: 0x55e2a1234000 —— 这就是在告诉你,它把字符串当指针打了地址。
测试私有成员或未导出函数怎么办?
gtest 本身不提供反射或友元注入机制。强行测私有函数会破坏封装,也增加维护成本。实际中优先考虑:
- 通过公有接口间接验证私有逻辑(例如调用
Calculate()后检查返回值和对象状态) - 把关键算法抽成独立的
static或free函数,放在头文件中并加inline,测试时直接调用 - 极少数必须测私有成员的场景,可在类定义末尾加
friend class TestClassName;,并在测试文件中定义同名测试类(注意命名空间匹配)
别为了测试而改生产代码的访问修饰符,更别用 #define private public 这种 hack —— 它会让编译器跳过访问检查,但可能破坏 ABI 或引发 ODR 违规。










