Google Test (gtest) 新手完全指南:从入门到精通

本文是专门为 C++ 测试新手编写的 gtest 教程,通过大量实际例子和通俗易懂的讲解,帮助您快速掌握这个强大的测试框架。

1. 什么是 Google Test?

1.1 测试框架是什么?

想象一下,你写了一段代码,想知道它是否按预期工作。你可以手动测试,但这样效率很低。测试框架就是帮你自动化这个过程的工具。

Google Test(gtest) 是 Google 开发的一个 C++ 测试框架,它让你能够:

  • 🚀 自动运行大量测试用例
  • 快速验证代码是否正确
  • 🔄 回归测试确保修改不破坏现有功能
  • 📊 生成报告展示测试结果

1.2 为什么需要测试?

cpp 复制代码
// 假设你写了一个计算器函数
int Divide(int a, int b) {
    return a / b;
}

// 手动测试很麻烦:
// 1. 编译程序
// 2. 运行程序
// 3. 输入测试数据
// 4. 检查输出是否正确
// 5. 重复以上步骤...

// 使用 gtest,你只需要写一次测试,然后自动运行

2. 环境搭建

2.1 安装 gtest

在 Ubuntu/Linux 上:

bash 复制代码
sudo apt-get install libgtest-dev
sudo apt-get install cmake  # 如果还没有安装 cmake

使用 CMake 管理项目(推荐):

cmake 复制代码
cmake_minimum_required(VERSION 3.14)
project(MyProject)

# 查找 gtest
find_package(GTest REQUIRED)

# 创建可执行文件
add_executable(my_tests test.cpp)

# 链接 gtest 库
target_link_libraries(my_tests GTest::gtest GTest::gtest_main)

2.2 验证安装

创建一个简单的测试文件 test_basic.cpp

cpp 复制代码
#include <gtest/gtest.h>

TEST(BasicTest, OnePlusOne) {
    EXPECT_EQ(1 + 1, 2);
}

int main(int argc, char **argv) {
    testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}

编译并运行:

bash 复制代码
g++ -std=c++11 test_basic.cpp -lgtest -lgtest_main -pthread -o test_basic
./test_basic

如果看到测试通过的输出,说明安装成功!

3. 第一个 gtest 程序

让我们从一个完整的例子开始:

cpp 复制代码
#include <gtest/gtest.h>
#include <string>

// 要测试的函数
std::string Greet(const std::string& name) {
    return "Hello, " + name + "!";
}

int Add(int a, int b) {
    return a + b;
}

// 最简单的测试用例
TEST(FunctionTest, GreetFunction) {
    EXPECT_EQ(Greet("Alice"), "Hello, Alice!");
    EXPECT_EQ(Greet("Bob"), "Hello, Bob!");
}

TEST(FunctionTest, AddFunction) {
    EXPECT_EQ(Add(2, 3), 5);
    EXPECT_EQ(Add(-1, 1), 0);
    EXPECT_EQ(Add(0, 0), 0);
}

// 另一个测试套件
TEST(StringTest, BasicOperations) {
    std::string str = "hello";
    
    EXPECT_EQ(str.length(), 5);
    EXPECT_EQ(str + " world", "hello world");
    EXPECT_NE(str, "goodbye");
}

int main(int argc, char **argv) {
    // 初始化 gtest
    testing::InitGoogleTest(&argc, argv);
    
    std::cout << "🎯 开始运行测试..." << std::endl;
    
    // 运行所有测试
    return RUN_ALL_TESTS();
}

输出结果:

复制代码
🎯 开始运行测试...
[==========] Running 3 tests from 2 test suites.
[----------] Global test environment set-up.
[----------] 2 tests from FunctionTest
[ RUN      ] FunctionTest.GreetFunction
[       OK ] FunctionTest.GreetFunction (0 ms)
[ RUN      ] FunctionTest.AddFunction
[       OK ] FunctionTest.AddFunction (0 ms)
[----------] 2 tests from FunctionTest (0 ms total)

[----------] 1 test from StringTest
[ RUN      ] StringTest.BasicOperations
[       OK ] StringTest.BasicOperations (0 ms)
[----------] 1 test from StringTest (0 ms total)

[----------] Global test environment tear-down.
[==========] 3 tests from 2 test suites ran. (1 ms total)
[  PASSED  ] 3 tests.

4. 理解 TEST 宏

4.1 TEST 宏的基本结构

cpp 复制代码
TEST(TestSuiteName, TestName) {
    // 测试代码
}
  • TestSuiteName:测试套件名称,用于分组相关的测试
  • TestName:具体的测试名称,描述要测试什么

4.2 实际例子

cpp 复制代码
#include <gtest/gtest.h>

TEST(MathTest, Addition) {
    // 这个测试属于 "MathTest" 套件,测试加法
    EXPECT_EQ(1 + 1, 2);
    EXPECT_EQ(10 + 20, 30);
}

TEST(MathTest, Subtraction) {
    // 同样属于 "MathTest" 套件,但测试减法
    EXPECT_EQ(5 - 3, 2);
    EXPECT_EQ(0 - 5, -5);
}

TEST(StringTest, Length) {
    // 这个测试属于 "StringTest" 套件
    std::string str = "hello";
    EXPECT_EQ(str.length(), 5);
}

TEST(StringTest, Concatenation) {
    std::string s1 = "hello";
    std::string s2 = " world";
    EXPECT_EQ(s1 + s2, "hello world");
}

5. 常用断言宏

gtest 提供了丰富的断言宏来验证结果:

5.1 基本断言

cpp 复制代码
TEST(AssertionTest, BasicExamples) {
    int value = 42;
    std::string text = "hello";
    
    // 相等检查
    EXPECT_EQ(value, 42);        // 期望相等
    ASSERT_EQ(value, 42);        // 断言相等(失败则终止测试)
    
    // 不等检查
    EXPECT_NE(value, 0);         // 期望不等
    
    // 大小比较
    EXPECT_GT(value, 30);        // 大于
    EXPECT_LT(value, 50);        // 小于
    EXPECT_GE(value, 42);        // 大于等于
    EXPECT_LE(value, 42);        // 小于等于
    
    // 布尔检查
    EXPECT_TRUE(value > 0);      // 期望为真
    EXPECT_FALSE(value < 0);     // 期望为假
    
    // 字符串检查
    EXPECT_STREQ(text.c_str(), "hello");    // C字符串相等
    EXPECT_STRNE(text.c_str(), "world");    // C字符串不等
}

5.2 EXPECT vs ASSERT 的区别

cpp 复制代码
TEST(ExpectVsAssert, Difference) {
    // EXPECT: 测试继续执行,即使失败
    EXPECT_EQ(1, 2);        // 失败,但继续执行
    EXPECT_EQ(3, 3);        // 这个仍然会执行
    
    // ASSERT: 测试立即终止,如果失败
    ASSERT_EQ(1, 1);        // 成功,继续执行
    // ASSERT_EQ(1, 2);     // 如果取消注释,测试会在这里终止
    // EXPECT_EQ(3, 3);     // 这行不会执行
}

5.3 浮点数比较

cpp 复制代码
TEST(FloatingPointTest, FloatComparison) {
    double a = 1.0 / 3.0;
    double b = 0.333333;
    
    // 错误的比较方式
    // EXPECT_EQ(a, b);     // 可能失败,因为浮点数精度问题
    
    // 正确的比较方式
    EXPECT_NEAR(a, b, 0.001);    // 允许0.001的误差
    EXPECT_DOUBLE_EQ(1.0, 1.0);  // 精确比较double
    EXPECT_FLOAT_EQ(1.0f, 1.0f); // 精确比较float
}

6. 局部环境测试(Test Fixtures)

6.1 什么是测试夹具?

想象你要测试一个银行账户类,每个测试都需要:

  1. 创建一个账户对象
  2. 设置初始余额
  3. 测试完成后清理资源

测试夹具(Test Fixtures) 就是帮你自动化这个过程的工具。

6.2 创建测试夹具

cpp 复制代码
#include <gtest/gtest.h>
#include <string>
#include <vector>

// 业务类:银行账户
class BankAccount {
public:
    BankAccount(const std::string& name, double balance) 
        : name_(name), balance_(balance) {}
    
    void Deposit(double amount) { 
        balance_ += amount; 
        transaction_count_++;
    }
    
    bool Withdraw(double amount) {
        if (amount <= balance_) {
            balance_ -= amount;
            transaction_count_++;
            return true;
        }
        return false;
    }
    
    double GetBalance() const { return balance_; }
    std::string GetName() const { return name_; }
    int GetTransactionCount() const { return transaction_count_; }
    
private:
    std::string name_;
    double balance_;
    int transaction_count_ = 0;
};

// 测试夹具类 - 必须继承 testing::Test
class BankAccountTest : public testing::Test {
protected:
    // 每个测试用例开始前执行
    void SetUp() override {
        std::cout << "🔄 设置银行账户测试环境" << std::endl;
        
        // 创建测试账户
        account1 = new BankAccount("张三", 1000.0);
        account2 = new BankAccount("李四", 500.0);
    }
    
    // 每个测试用例结束后执行
    void TearDown() override {
        std::cout << "🧹 清理银行账户测试环境" << std::endl;
        
        // 清理资源
        delete account1;
        delete account2;
        account1 = nullptr;
        account2 = nullptr;
    }
    
    // 辅助函数
    void ResetAccounts() {
        delete account1;
        delete account2;
        account1 = new BankAccount("张三", 1000.0);
        account2 = new BankAccount("李四", 500.0);
    }
    
    // 所有测试用例都可以访问的成员
    BankAccount* account1;
    BankAccount* account2;
};

6.3 使用 TEST_F 宏

cpp 复制代码
// 使用 TEST_F 而不是 TEST
// F 代表 Fixture(夹具)

TEST_F(BankAccountTest, InitialState) {
    // 可以直接使用夹具中的 account1 和 account2
    EXPECT_EQ(account1->GetBalance(), 1000.0);
    EXPECT_EQ(account1->GetName(), "张三");
    EXPECT_EQ(account2->GetBalance(), 500.0);
    EXPECT_EQ(account2->GetName(), "李四");
}

TEST_F(BankAccountTest, DepositOperations) {
    // 测试存款
    account1->Deposit(500.0);
    EXPECT_EQ(account1->GetBalance(), 1500.0);
    EXPECT_EQ(account1->GetTransactionCount(), 1);
    
    account1->Deposit(100.0);
    EXPECT_EQ(account1->GetBalance(), 1600.0);
    EXPECT_EQ(account1->GetTransactionCount(), 2);
}

TEST_F(BankAccountTest, WithdrawOperations) {
    // 测试取款
    bool success = account1->Withdraw(300.0);
    EXPECT_TRUE(success);
    EXPECT_EQ(account1->GetBalance(), 700.0);
    
    // 测试余额不足
    success = account1->Withdraw(2000.0);
    EXPECT_FALSE(success);
    EXPECT_EQ(account1->GetBalance(), 700.0);  // 余额不变
}

6.4 测试夹具的执行流程

对于上面的 BankAccountTest

复制代码
运行 TEST_F(BankAccountTest, InitialState):
1. BankAccountTest::SetUp() - 创建账户
2. 执行测试代码
3. BankAccountTest::TearDown() - 删除账户

运行 TEST_F(BankAccountTest, DepositOperations):
1. BankAccountTest::SetUp() - 创建新账户(重新初始化)
2. 执行测试代码
3. BankAccountTest::TearDown() - 删除账户

关键点:每个测试用例都有全新的环境,互不干扰!

7. 全局环境测试(Global Test Environment)

7.1 什么是全局环境?

当所有测试用例需要共享相同的全局设置时,可以使用全局环境。

适用场景:

  • 🌐 建立数据库连接
  • ⚙️ 初始化全局配置
  • 📁 准备测试文件
  • ⏱️ 统计测试总时间

7.2 创建全局环境

cpp 复制代码
#include <gtest/gtest.h>
#include <iostream>
#include <chrono>
#include <fstream>

// 全局测试环境类 - 必须继承 testing::Environment
class GlobalTestEnvironment : public testing::Environment {
public:
    // 在所有测试开始前执行(只执行一次)
    virtual void SetUp() override {
        std::cout << "🌍 全局测试环境初始化" << std::endl;
        std::cout << "================================" << std::endl;
        
        start_time = std::chrono::steady_clock::now();
        
        // 模拟全局初始化工作
        database_connected = ConnectToDatabase();
        config_loaded = LoadConfiguration();
        test_file_created = CreateTestFile();
        
        std::cout << "✅ 数据库连接: " << (database_connected ? "成功" : "失败") << std::endl;
        std::cout << "✅ 配置文件加载: " << (config_loaded ? "成功" : "失败") << std::endl;
        std::cout << "✅ 测试文件创建: " << (test_file_created ? "成功" : "失败") << std::endl;
    }
    
    // 在所有测试结束后执行(只执行一次)
    virtual void TearDown() override {
        auto end_time = std::chrono::steady_clock::now();
        auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(
            end_time - start_time);
        
        std::cout << "================================" << std::endl;
        std::cout << "🌍 全局测试环境清理" << std::endl;
        std::cout << "⏱️  测试总耗时: " << duration.count() << " 毫秒" << std::endl;
        
        // 模拟全局清理工作
        DisconnectDatabase();
        CleanupTestFile();
        
        std::cout << "✅ 数据库已断开连接" << std::endl;
        std::cout << "✅ 测试文件已清理" << std::endl;
    }
    
    // 全局状态访问方法
    static bool IsDatabaseConnected() { return database_connected; }
    static bool IsConfigLoaded() { return config_loaded; }
    
private:
    // 模拟全局操作
    bool ConnectToDatabase() {
        std::cout << "连接数据库中..." << std::endl;
        return true;
    }
    
    bool LoadConfiguration() {
        std::cout << "加载配置文件中..." << std::endl;
        return true;
    }
    
    bool CreateTestFile() {
        std::ofstream file("test_temp.txt");
        if (file) {
            file << "临时测试文件内容";
            file.close();
            return true;
        }
        return false;
    }
    
    void DisconnectDatabase() {
        database_connected = false;
    }
    
    void CleanupTestFile() {
        remove("test_temp.txt");
    }
    
    std::chrono::steady_clock::time_point start_time;
    
    // 全局状态
    static bool database_connected;
    static bool config_loaded;
    static bool test_file_created;
};

// 初始化静态成员
bool GlobalTestEnvironment::database_connected = false;
bool GlobalTestEnvironment::config_loaded = false;
bool GlobalTestEnvironment::test_file_created = false;

7.3 注册和使用全局环境

cpp 复制代码
// 普通的测试用例
TEST(DatabaseTest, ConnectionStatus) {
    // 可以检查全局环境的状态
    EXPECT_TRUE(GlobalTestEnvironment::IsDatabaseConnected());
    EXPECT_TRUE(GlobalTestEnvironment::IsConfigLoaded());
}

TEST(APITest, BasicFunctionality) {
    // 假设这些测试依赖于全局的数据库连接
    EXPECT_TRUE(GlobalTestEnvironment::IsDatabaseConnected());
    
    // 模拟一些测试逻辑
    int result = 2 + 3;
    EXPECT_EQ(result, 5);
}

// 文件操作测试
TEST(FileTest, FileExistence) {
    // 检查测试文件是否存在(依赖全局环境创建的文件)
    std::ifstream file("test_temp.txt");
    bool file_exists = file.good();
    file.close();
    EXPECT_TRUE(file_exists);
}

int main(int argc, char **argv) {
    // 初始化 gtest
    testing::InitGoogleTest(&argc, argv);
    
    // 注册全局测试环境 - 必须步骤!
    testing::AddGlobalTestEnvironment(new GlobalTestEnvironment);
    
    std::cout << "🚀 开始运行测试套件..." << std::endl;
    int result = RUN_ALL_TESTS();
    std::cout << "🎉 测试套件运行完成" << std::endl;
    
    return result;
}

8. TEST vs TEST_F:关键区别

8.1 语法区别

cpp 复制代码
// TEST 宏:用于简单测试
TEST(TestSuiteName, TestName) {
    // 测试代码
}

// TEST_F 宏:用于基于夹具的测试
TEST_F(TestFixtureClassName, TestName) {
    // 测试代码
}

8.2 功能对比

特性 TEST 宏 TEST_F 宏
是否需要夹具类 ❌ 不需要 ✅ 必须继承 ::testing::Test
设置清理 手动处理 自动通过 SetUp()/TearDown()
数据共享 不能共享设置代码 共享夹具类的成员和方法
执行时机 直接执行 每个测试前调用SetUp,后调用TearDown
适用场景 简单、独立测试 复杂初始化、资源管理

8.3 实际选择指南

使用 TEST:

cpp 复制代码
// 简单数学运算
TEST(MathTest, BasicOperations) {
    EXPECT_EQ(1 + 1, 2);
    EXPECT_EQ(10 * 2, 20);
}

// 字符串操作
TEST(StringTest, Concatenation) {
    std::string s1 = "hello";
    std::string s2 = " world";
    EXPECT_EQ(s1 + s2, "hello world");
}

使用 TEST_F:

cpp 复制代码
// 需要复杂设置的测试
class DatabaseTest : public testing::Test {
protected:
    void SetUp() override { /* 连接数据库 */ }
    void TearDown() override { /* 断开连接 */ }
};

TEST_F(DatabaseTest, QueryTest) {
    // 测试数据库查询
}

TEST_F(DatabaseTest, InsertTest) {
    // 测试数据插入
}

9. 完整项目示例

让我们用一个完整的例子来总结所学内容:

cpp 复制代码
#include <gtest/gtest.h>
#include <iostream>
#include <string>
#include <vector>
#include <memory>
#include <stdexcept>

// ==================== 全局环境 ====================
class ProjectTestEnvironment : public testing::Environment {
public:
    static int total_tests;
    
    void SetUp() override {
        std::cout << "🧪 项目测试套件开始" << std::endl;
        total_tests = 0;
        std::cout << "初始化日志系统..." << std::endl;
        std::cout << "加载应用配置..." << std::endl;
    }
    
    void TearDown() override {
        std::cout << "🧪 项目测试套件结束" << std::endl;
        std::cout << "📊 总共运行了 " << total_tests << " 个测试" << std::endl;
        std::cout << "清理日志系统..." << std::endl;
    }
};

int ProjectTestEnvironment::total_tests = 0;

// ==================== 业务代码 ====================
class Calculator {
public:
    int Add(int a, int b) { return a + b; }
    int Subtract(int a, int b) { return a - b; }
    int Multiply(int a, int b) { return a * b; }
    double Divide(double a, double b) { 
        if (b == 0) throw std::invalid_argument("除数不能为零");
        return a / b; 
    }
};

class UserManager {
public:
    void AddUser(const std::string& name) { 
        users.push_back(name); 
        user_count++;
    }
    
    bool UserExists(const std::string& name) {
        for (const auto& user : users) {
            if (user == name) return true;
        }
        return false;
    }
    
    int GetUserCount() { return user_count; }
    void ClearUsers() { 
        users.clear(); 
        user_count = 0;
    }
    
private:
    std::vector<std::string> users;
    int user_count = 0;
};

// ==================== 局部测试环境 ====================
class CalculatorTest : public testing::Test {
protected:
    void SetUp() override {
        calculator = std::make_unique<Calculator>();
        ProjectTestEnvironment::total_tests++;
    }
    
    void TearDown() override {
        // unique_ptr 自动管理内存
    }
    
    std::unique_ptr<Calculator> calculator;
};

class UserManagerTest : public testing::Test {
protected:
    void SetUp() override {
        manager = std::make_unique<UserManager>();
        ProjectTestEnvironment::total_tests++;
        
        // 预先添加测试用户
        manager->AddUser("admin");
        manager->AddUser("guest");
    }
    
    void TearDown() override {
        // unique_ptr 自动清理
    }
    
    std::unique_ptr<UserManager> manager;
};

// ==================== 测试用例 ====================

// 使用 TEST 的简单测试
TEST(SimpleMathTest, BasicOperations) {
    EXPECT_EQ(1 + 1, 2);
    EXPECT_EQ(10 * 2, 20);
    EXPECT_GT(100, 50);
}

// 使用 TEST_F 的计算器测试
TEST_F(CalculatorTest, Addition) {
    EXPECT_EQ(calculator->Add(2, 3), 5);
    EXPECT_EQ(calculator->Add(-1, 1), 0);
    EXPECT_EQ(calculator->Add(0, 0), 0);
}

TEST_F(CalculatorTest, Multiplication) {
    EXPECT_EQ(calculator->Multiply(4, 5), 20);
    EXPECT_EQ(calculator->Multiply(0, 100), 0);
    EXPECT_EQ(calculator->Multiply(-2, 3), -6);
}

TEST_F(CalculatorTest, Division) {
    EXPECT_EQ(calculator->Divide(10, 2), 5);
    EXPECT_EQ(calculator->Divide(9, 3), 3);
    EXPECT_THROW(calculator->Divide(10, 0), std::invalid_argument);
}

// 使用 TEST_F 的用户管理器测试
TEST_F(UserManagerTest, InitialUsers) {
    EXPECT_EQ(manager->GetUserCount(), 2);
    EXPECT_TRUE(manager->UserExists("admin"));
    EXPECT_TRUE(manager->UserExists("guest"));
}

TEST_F(UserManagerTest, AddNewUsers) {
    manager->AddUser("alice");
    manager->AddUser("bob");
    
    EXPECT_EQ(manager->GetUserCount(), 4);
    EXPECT_TRUE(manager->UserExists("alice"));
    EXPECT_TRUE(manager->UserExists("bob"));
    EXPECT_FALSE(manager->UserExists("charlie"));
}

TEST_F(UserManagerTest, ClearUsers) {
    manager->ClearUsers();
    EXPECT_EQ(manager->GetUserCount(), 0);
    EXPECT_FALSE(manager->UserExists("admin"));
}

// ==================== 主函数 ====================
int main(int argc, char **argv) {
    testing::InitGoogleTest(&argc, argv);
    
    // 注册全局环境
    testing::AddGlobalTestEnvironment(new ProjectTestEnvironment);
    
    std::cout << "==========================================" << std::endl;
    std::cout << "    Google Test 完整示例程序" << std::endl;
    std::cout << "    演示 TEST 和 TEST_F 的用法" << std::endl;
    std::cout << "==========================================" << std::endl;
    
    int result = RUN_ALL_TESTS();
    
    std::cout << "==========================================" << std::endl;
    std::cout << "程序退出代码: " << result << " (0表示所有测试通过)" << std::endl;
    
    return result;
}

10. 编译和运行

10.1 使用 g++ 编译

bash 复制代码
# 编译并运行完整示例
g++ -std=c++11 -o my_tests main.cpp -lgtest -lgtest_main -pthread
./my_tests

10.2 使用 CMake(推荐)

创建 CMakeLists.txt

cmake 复制代码
cmake_minimum_required(VERSION 3.14)
project(MyGTestProject)

find_package(GTest REQUIRED)

add_executable(my_tests main.cpp)
target_link_libraries(my_tests GTest::gtest GTest::gtest_main pthread)

编译运行:

bash 复制代码
mkdir build
cd build
cmake ..
make
./my_tests

11. 最佳实践和常见问题

11.1 测试命名规范

cpp 复制代码
// 好的命名
TEST(UserAuthenticationTest, ValidLoginSucceeds)
TEST(CalculatorTest, DivisionByZeroThrowsException)
TEST(FileManagerTest, CreateNewFileWithValidPath)

// 不好的命名  
TEST(Test1, Test1)  // 太模糊
TEST(user, test)    // 不清晰

11.2 测试组织原则

cpp 复制代码
// 相关测试分组到同一个套件
TEST(NetworkTest, ConnectToServer)
TEST(NetworkTest, SendData)
TEST(NetworkTest, ReceiveData)

// 不同功能使用不同套件
TEST(DatabaseTest, InsertRecord)
TEST(DatabaseTest, QueryRecords)
TEST(FileSystemTest, CreateFile)
TEST(FileSystemTest, DeleteFile)

11.3 常见错误和解决方案

错误1:忘记链接 pthread

复制代码
错误:未定义的引用 to 'pthread_create'
解决:编译时添加 -pthread 参数

错误2:TEST_F 使用错误的夹具类名

cpp 复制代码
// 错误
TEST_F(WrongClassName, TestName)  // 夹具类不存在

// 正确
TEST_F(CalculatorTest, TestName)  // 使用已定义的夹具类

错误3:全局环境忘记注册

cpp 复制代码
// 错误:只定义不注册
class MyEnvironment : public testing::Environment { /* ... */ };

// 正确:必须注册
testing::AddGlobalTestEnvironment(new MyEnvironment);

12. 总结

通过这个完整的教程,我们学习了:

📚 核心概念

  • gtest 基础:测试框架的作用和优势
  • TEST 宏:用于简单测试,参数是测试套件名和测试名
  • TEST_F 宏:用于基于夹具的测试,参数是夹具类名和测试名
  • 断言宏:丰富的验证工具(EXPECT_EQ, ASSERT_TRUE等)

🛠️ 环境管理

  • 局部环境(夹具):用于测试用例级别的设置和清理
  • 全局环境:用于测试套件级别的设置和清理
  • 关键区别:局部环境不需要注册,全局环境必须注册

🎯 实践技巧

  • TEST vs TEST_F:根据测试复杂度选择合适的方法
  • 测试组织:合理的命名和分组
  • 编译运行:多种编译方式的选择

🚀 下一步学习

掌握了基础之后,您可以继续学习:

  • 参数化测试(TEST_P)
  • 类型参数化测试
  • 死亡测试(检查程序崩溃)
  • 模拟对象(Google Mock)

记住:好的测试是代码质量的守护者。开始在自己的项目中使用 gtest,您会发现代码变得更加健壮和可靠!

Happy testing!

相关推荐
zzzzzz3101 天前
9K Star 炸裂开源!这个 C 语言写的代码知识图谱,把 Linux 内核索引压缩到了 3 分钟
linux·服务器·sql
XIAOHEZIcode1 天前
Linux系统鼠标偏移常见原因以及修复方案
linux·运维·游戏
用户0328472220702 天前
如何搭建本地yum源(上)
运维
大树885 天前
金刚石散热越强,管路越先见顶
大数据·运维·服务器·人工智能·ai
摇滚侠5 天前
Linux CentOS7 rpm 安装 MySQL 5.7
linux·运维·mysql
霸道流氓气质5 天前
领域驱动设计(DDD)在 Spring Boot 微服务中的实践指南
运维·spring boot·微服务
小宇宙Zz5 天前
Maven依赖冲突
java·服务器·maven
Inhand陈工5 天前
基于台达PLC与映翰通IG502的智慧水产养殖精准投喂与远程运维解决方案
运维·人工智能·物联网·阿里云·信息与通信
网络研究院5 天前
2026年网络安全
网络·安全·法律·法规·趋势·发展
酣大智5 天前
ARP代理--工作原理
运维·网络·arp·arp代理