Gtest断言全指南:从EXPECT_EQ到ASSERT_NE的20种用法详解

张开发
2026/5/14 4:04:33 15 分钟阅读
Gtest断言全指南:从EXPECT_EQ到ASSERT_NE的20种用法详解
Gtest断言全指南从EXPECT_EQ到ASSERT_NE的20种用法详解在软件开发中单元测试是保证代码质量的重要环节。Google Test简称Gtest作为C领域广泛使用的测试框架其断言系统提供了丰富的验证手段。本文将深入解析Gtest断言机制涵盖数值比较、字符串校验、异常检测等常见场景特别剖析EXPECT_*和ASSERT_*系列的关键差异。1. Gtest断言基础EXPECT与ASSERT的本质区别Gtest断言分为两大系列EXPECT_和ASSERT_。它们的主要区别在于测试失败时的行为表现EXPECT_*非致命断言测试失败后继续执行后续测试代码ASSERT_*致命断言测试失败立即终止当前测试函数TEST(AssertDemo, BasicExample) { int x 5; EXPECT_EQ(x, 6); // 失败但继续执行 ASSERT_EQ(x, 5); // 成功则继续 EXPECT_EQ(x, 7); // 失败但继续 ASSERT_EQ(x, 8); // 失败并终止函数 EXPECT_EQ(x, 9); // 不会执行到这里 }提示优先使用EXPECT_*系列除非后续测试依赖前序断言的成功结果2. 数值比较断言20种核心用法详解2.1 基础比较断言断言类型等效表达式适用场景EXPECT_EQ(a,b)a b验证相等EXPECT_NE(a,b)a ! b验证不等EXPECT_LT(a,b)a b验证小于EXPECT_LE(a,b)a b验证小于等于EXPECT_GT(a,b)a b验证大于EXPECT_GE(a,b)a b验证大于等于TEST(NumericTest, BasicComparisons) { int val 42; EXPECT_EQ(val, 42); // 验证等于 EXPECT_NE(val, 0); // 验证不等于 EXPECT_LT(val, 100); // 验证小于 EXPECT_LE(val, 42); // 验证小于等于 EXPECT_GT(val, 30); // 验证大于 EXPECT_GE(val, 42); // 验证大于等于 }2.2 浮点数比较处理浮点数时应使用近似比较断言避免精度问题TEST(FloatTest, ApproximateComparison) { double x 1.0/3.0; EXPECT_FLOAT_EQ(x, 0.333333f); // 4字节浮点比较 EXPECT_DOUBLE_EQ(x, 0.333333333333); // 8字节浮点比较 EXPECT_NEAR(x, 0.333, 0.001); // 允许误差范围比较 }2.3 布尔和指针断言EXPECT_TRUE(condition)验证条件为真EXPECT_FALSE(condition)验证条件为假EXPECT_NULL(ptr)验证指针为空EXPECT_NOTNULL(ptr)验证指针非空TEST(PointerTest, NullCheck) { int* ptr nullptr; EXPECT_NULL(ptr); // 验证空指针 ptr new int(10); EXPECT_NOTNULL(ptr); // 验证非空指针 delete ptr; }3. 字符串与异常处理断言3.1 字符串比较Gtest提供多种字符串比较方式TEST(StringTest, Comparisons) { const char* cstr Hello; std::string str World; EXPECT_STREQ(cstr, Hello); // C字符串相等 EXPECT_STRNE(cstr, str.c_str()); // C字符串不等 EXPECT_STRCASEEQ(cstr, HELLO); // 忽略大小写比较 EXPECT_STRCASENE(cstr, WORLD); // 忽略大小写不等 }3.2 异常检测验证代码是否抛出预期异常void ThrowIfNegative(int x) { if (x 0) throw std::runtime_error(Negative!); } TEST(ExceptionTest, Handling) { EXPECT_NO_THROW(ThrowIfNegative(1)); // 验证无异常 EXPECT_THROW(ThrowIfNegative(-1), std::runtime_error); // 验证特定异常 EXPECT_ANY_THROW(ThrowIfNegative(-1)); // 验证任何异常 }4. 高级断言技巧与最佳实践4.1 自定义错误信息所有断言都支持附加自定义错误信息TEST(CustomMessage, Example) { int actual 5, expected 6; EXPECT_EQ(actual, expected) 实际值 actual 不等于期望值 expected; }4.2 谓词断言使用EXPECT_PRED*系列处理复杂验证逻辑bool IsEven(int n) { return n % 2 0; } TEST(PredicateTest, Example) { EXPECT_PRED1(IsEven, 4); // 验证单参数谓词 EXPECT_PRED_FORMAT2([](const char* expr, int a, int b) { return testing::AssertionResult(a b) expr expected a b; }, 5, 5); }4.3 死亡测试验证程序是否按预期终止void CrashIfZero(int x) { if (x 0) abort(); } TEST(DeathTest, Example) { EXPECT_DEATH(CrashIfZero(0), ); // 验证程序终止 EXPECT_DEATH_IF_SUPPORTED(CrashIfZero(0), ); // 条件支持时验证 }5. 断言在TEST与TEST_F中的实际应用5.1 TEST宏中的断言使用TEST(QueueTest, BasicOperations) { Queueint q; EXPECT_TRUE(q.Empty()); // 初始应为空 q.Enqueue(1); EXPECT_FALSE(q.Empty()); // 添加后非空 EXPECT_EQ(q.Size(), 1); // 大小应为1 int val q.Dequeue(); EXPECT_EQ(val, 1); // 取出值验证 EXPECT_TRUE(q.Empty()); // 取出后应为空 }5.2 TEST_F宏中的断言使用class QueueTest : public ::testing::Test { protected: void SetUp() override { q1_.Enqueue(1); q2_.Enqueue(2); q2_.Enqueue(3); } Queueint q0_; Queueint q1_; Queueint q2_; }; TEST_F(QueueTest, IsEmptyInitially) { EXPECT_EQ(q0_.Size(), 0); // 初始队列应为空 } TEST_F(QueueTest, DequeueWorks) { int* n q0_.Dequeue(); EXPECT_NULL(n); // 空队列应返回null n q1_.Dequeue(); ASSERT_NOTNULL(n); // 关键断言失败则终止 EXPECT_EQ(*n, 1); // 验证取值 EXPECT_EQ(q1_.Size(), 0); delete n; }在实际项目中合理组合使用这些断言可以构建出健壮的测试套件。例如在测试网络模块时EXPECT_系列适合验证连续的状态变化而ASSERT_系列则适用于关键前置条件的检查。

更多文章