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!

相关推荐
luback2 小时前
前端对Docker简单了解
运维·docker·容器
0思必得02 小时前
[Web自动化] 开发者工具应用(Application)面板
运维·前端·python·自动化·web自动化·开发者工具
发光小北2 小时前
SG-PNh750-TCP-210(Profinet 从站转 Modbus TCP 网关)
网络·网络协议·tcp/ip
LEEE@FPGA2 小时前
ZYNQ MPSOC linux hello world
linux·运维·服务器
郝学胜-神的一滴2 小时前
Linux定时器编程:深入理解setitimer函数
linux·服务器·开发语言·c++·程序人生
漏洞文库-Web安全3 小时前
Linux逆向学习记录
linux·运维·学习·安全·web安全·网络安全·逆向
无奈笑天下3 小时前
【银河麒麟高级服务器部署本地yum源】
linux·运维·服务器·经验分享
wanhengidc3 小时前
云手机 数字生活中新的可能
运维·服务器·科技·安全·智能手机·生活
Likeadust3 小时前
视频直播点播平台EasyDSS助力企业打造全场景数字化宣传体系
运维·人工智能·音视频