本文通过一个可直接编译运行的 C++17 工程,集中演示 GoogleTest 中常用的布尔、比较、字符串、浮点、异常、谓词、测试夹具和进程终止断言。工程已经在 Windows、Visual Studio 2022 和 GoogleTest 1.15.2 环境下验证,17 个测试全部通过。
一、为什么要分类学习 GoogleTest 断言
很多人第一次接触 GoogleTest,只会写:
EXPECT_EQ(actual,expected);但真实项目中的故障不只有“两个值不相等”:
- 一个布尔条件可能不成立。
- 两个 C 风格字符串内容可能不同。
- 浮点结果可能存在舍入误差。
- 函数可能抛出错误类型的异常。
- 被测代码可能异常终止或主动退出进程。
- 前置条件失败后,继续执行测试可能导致二次崩溃。
GoogleTest 为这些场景提供了不同的断言。选择正确的断言,不只是让测试通过或失败,还能让失败报告更准确,并控制失败之后是否继续执行当前测试。
- 前置条件失败后,继续执行测试可能导致二次崩溃。
二、工程结构
示例工程名为GTest_Assertions_Showcase,目录如下:
GTest_Assertions_Showcase/ ├── CMakeLists.txt ├── README.md ├── include/ │ └── sample_functions.h ├── src/ │ └── sample_functions.cpp └── tests/ ├── test_basic_assertions.cpp ├── test_death_and_exit.cpp ├── test_exception_assertions.cpp ├── test_fixture.cpp ├── test_floating_point_assertions.cpp ├── test_predicate_assertions.cpp └── test_string_assertions.cpp测试按类别拆分,便于把每一种断言与适用场景对应起来。
三、断言速查表
| 类别 | 常用接口 |
|---|---|
| 布尔判断 | EXPECT_TRUE、EXPECT_FALSE |
| 相等与大小关系 | EXPECT_EQ、EXPECT_NE、EXPECT_LT、EXPECT_LE、EXPECT_GT、EXPECT_GE |
| C 风格字符串 | EXPECT_STREQ、EXPECT_STRNE、EXPECT_STRCASEEQ、EXPECT_STRCASENE |
| 浮点数 | EXPECT_FLOAT_EQ、EXPECT_DOUBLE_EQ、EXPECT_NEAR |
| 异常 | EXPECT_THROW、EXPECT_ANY_THROW、EXPECT_NO_THROW |
| 自定义谓词 | EXPECT_PRED1、EXPECT_PRED2 |
| 进程终止 | EXPECT_DEATH、EXPECT_EXIT |
| 测试夹具 | TEST_F、SetUp、TearDown |
| 显式成功 | SUCCEED |
大部分EXPECT_*都有对应的ASSERT_*版本。
四、EXPECT 与 ASSERT 的本质区别
EXPECT_*和ASSERT_*最重要的区别是失败之后的控制流。
EXPECT:记录失败后继续执行
EXPECT_EQ(actual,expected);// 即使上面的断言失败,当前测试仍会继续向下执行。它适合相互独立的检查。一次测试可以收集多个失败信息,减少“修一个、跑一次、再发现下一个”的次数。
ASSERT:失败后立即结束当前测试
ASSERT_NE(pointer,nullptr);EXPECT_EQ(*pointer,42);如果指针为空,第二行解引用就没有继续执行的意义。此时必须使用ASSERT_NE建立前置条件:
TEST(FatalAssertions,StopOnlyTheCurrentTestOnFailure){constintvalue=42;constint*pointer=&value;ASSERT_NE(pointer,nullptr);EXPECT_EQ(*pointer,42);}需要注意,ASSERT_*只会终止当前测试函数,不会终止整个测试程序。
一个实用原则是:
- 检查测试前置条件时使用
ASSERT_*。 - 检查可以相互独立报告的结果时使用
EXPECT_*。
- 检查可以相互独立报告的结果时使用
五、布尔和比较断言
1. 布尔断言
TEST(BooleanAssertions,CheckTrueAndFalse){EXPECT_TRUE(sample::is_even(4));EXPECT_FALSE(sample::is_even(5));}``` 这比写成下面的形式更能表达意图: ```cppEXPECT_EQ(sample::is_even(4),true);2. 比较断言
TEST(ComparisonAssertions,CheckEqualityAndOrdering){EXPECT_EQ(sample::add(2,3)