TEST()用于简单独立测试,无需初始化;TEST_F()需配合派生自::testing::Test的夹具类,含SetUp()/TearDown()确保隔离性;命名用驼峰式,避免下划线;夹具中勿用静态成员跨测试共享状态。

TEST宏怎么写,什么时候该用它
直接用TEST()就行,适合单个测试逻辑简单、不依赖共享状态的场景。它不带任何前置初始化或清理,每个测试都是干净独立的。
常见错误是把测试名或用例名写成带下划线的风格(比如test_addition),虽然编译能过,但和Google Test内部命名约定冲突,容易在参数化测试或过滤时出问题。推荐用驼峰式,比如TestAddition。
-
TEST()第一个参数是测试套件名(逻辑分组),第二个是测试名,两者都必须是合法C++标识符 - 不能在
TEST()里访问局部变量以外的共享对象——想用全局变量?别这么做,会破坏测试隔离性 - 如果只是验证一个纯函数(比如
int add(int a, int b)),TEST()足够了,不用上夹具
TEST_F宏必须配测试夹具类,漏掉就编译报错
TEST_F()不是单独存在的,它必须搭配一个从::testing::Test派生的类,否则你会看到类似virtual outside class declaration的编译错误。
这个夹具类名字就是TEST_F()的第一个参数,拼写必须完全一致,大小写敏感。最容易踩的坑是把SetUp()写成Setup()(少个大写U)——函数不会被调用,但编译器不报错,导致测试环境始终没初始化。
- 夹具类里所有要共用的对象必须声明为
protected或public,否则TEST_F()里访问不到 -
SetUp()和TearDown()是override函数,记得加override关键字,避免签名不匹配却无声失败 - 每次运行
TEST_F()都会新建一个夹具实例,所以不同测试之间互不影响——这点别指望靠夹具类的静态成员来“跨测试传值”
夹具类里该放什么,不该放什么
夹具类的核心作用是“让多个测试复用同一套初始化/清理逻辑”,不是用来塞业务逻辑或全局状态的。
比如你要测一个Queue类,夹具里可以放Queue<int> queue_;</int>,并在SetUp()里清空它;但不要放static std::vector<int> global_cache;</int>,那会让测试耦合、不可预测。
- 推荐在
SetUp()里做资源分配(如new、mock setup)、状态重置;在TearDown()里做释放(delete、reset mock) - 构造函数和析构函数也能用,但要注意:如果
SetUp()抛异常,构造函数已执行完,而析构函数不会被调用——所以资源清理尽量收口到TearDown() - 如果某个对象在所有测试中只读、且构造开销大(比如加载配置文件),可以考虑用
static成员 +SetUpTestSuite()/TearDownTestSuite(),但这是进阶用法,普通夹具别碰
TEST和TEST_F混用时的链接与可见性陷阱
同一个源文件里同时有TEST()和TEST_F()没问题,但要注意它们的符号作用域是隔离的:TEST()里定义的变量对TEST_F()不可见,反之亦然。
更隐蔽的问题是链接阶段:如果你把夹具类定义在头文件里,又在多个.cc文件中include它,可能触发ODR(One Definition Rule)违规,尤其当夹具里有inline函数或模板时。解决方案是把夹具类定义放在.cc里,或者确保头文件里用inline或static约束。
- 别在夹具类头文件里写
std::unique_ptr<Mock> mock_;然后在多个TU中include——除非你明确用了extern template或分离定义 - 如果用CMake +
FetchContent引入gtest,确保所有测试目标都链接GTest::gtest,而不是只链gtest_main——后者不含TEST_F所需的模板实例化代码 - 调试时发现夹具的
SetUp()没执行?先检查是否误用了TEST()而不是TEST_F(),这是最常被忽略的拼写级失误


















