Google Test 学习笔记

1. Google Test 基础

1.1 TEST 和断言

TEST:用于定义测试用例。

  • 第一个参数是测试套件名称。
  • 第二个参数是测试名称。

示例:

1
2
3
4
5
6
7
int Add(int a, int b) {
return a + b;
}

TEST(AddTest, HandlesPositiveNumbers) {
EXPECT_EQ(Add(1, 2), 3);
}

常用断言:

  • EXPECT_EQ(val1, val2):检查 val1 == val2
  • EXPECT_NE(val1, val2):检查 val1 != val2
  • EXPECT_LT(val1, val2):检查 val1 < val2
  • EXPECT_LE(val1, val2):检查 val1 <= val2
  • EXPECT_GT(val1, val2):检查 val1 > val2
  • EXPECT_GE(val1, val2):检查 val1 >= val2
  • ASSERT_*:与 EXPECT_* 类似,但失败时会终止测试。

1.2 TEST_F 和测试夹具

  • 用于测试需要共享代码或状态的情况。
  • 继承 ::testing::Test 创建测试夹具。

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class MathTest : public ::testing::Test {
protected:
void SetUp() override {
a = 10;
b = 5;
}

int a, b;
};

TEST_F(MathTest, Addition) {
EXPECT_EQ(a + b, 15);
}

TEST_F(MathTest, Subtraction) {
EXPECT_EQ(a - b, 5);
}

2. 异常处理

  • 检查函数是否抛出异常。

常用断言

  • EXPECT_THROW(expression, exception_type):检查是否抛出指定类型异常。
  • EXPECT_ANY_THROW(expression):检查是否抛出任意异常。
  • EXPECT_NO_THROW(expression):检查是否未抛出异常。

示例:

1
2
3
4
5
6
7
8
9
10
11
int Division(int a, int b) {
if (b == 0) {
throw std::invalid_argument("Division by zero");
}
return a / b;
}

TEST(ExceptionTest, HandlesExceptions) {
EXPECT_THROW(Division(10, 0), std::invalid_argument);
EXPECT_NO_THROW(Division(10, 2));
}

3. 参数化测试

  • 适用于需要在多组输入下测试相同逻辑的情况。

3.1 定义参数化测试

  • 继承 ::testing::TestWithParam<ParamType>
  • 使用 TEST_P 定义测试。
  • 调用 GetParam() 获取当前参数。

3.2 实例化测试

  1. 使用 INSTANTIATE_TEST_SUITE_P 定义参数列表。

示例:

1
2
3
4
5
6
7
8
9
10
11
12
class ParamTest : public ::testing::TestWithParam<int> {};

TEST_P(ParamTest, IsEven) {
int n = GetParam();
EXPECT_EQ(n % 2, 0);
}

INSTANTIATE_TEST_SUITE_P(
EvenNumbersTest,
ParamTest,
::testing::Values(2, 4, 6, 8)
);
  1. 动态生成参数:

使用 ::testing::Combine 创建参数笛卡尔积。

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <tuple>

class MultiParamTest : public ::testing::TestWithParam<std::tuple<int, int>> {};

TEST_P(MultiParamTest, Multiply) {
int a, b;
std::tie(a, b) = GetParam();
EXPECT_EQ(a * b, a * b);
}

INSTANTIATE_TEST_SUITE_P(
GenerateTests,
MultiParamTest,
::testing::Combine(
::testing::Values(1, 2),
::testing::Values(3, 4)
)
);

4. Mock(模拟对象)

  • 用于测试依赖于外部资源或模块的函数。
  • 需要引入 gmock

4.1 定义 Mock 类

  • 使用 MOCK_METHOD 定义接口方法的模拟。

接口定义:

1
2
3
4
5
class Calculator {
public:
virtual ~Calculator() = default;
virtual int Add(int a, int b) = 0;
};

模拟类:

1
2
3
4
5
6
#include <gmock/gmock.h>

class MockCalculator : public Calculator {
public:
MOCK_METHOD(int, Add, (int a, int b), (override));
};

4.2 设置期望行为

  • EXPECT_CALL(mock, Method(args)):定义期望的调用和返回值。
  • 使用 WillOnceWillRepeatedly 指定返回值。

示例:

1
2
3
4
5
6
7
8
9
TEST(MockTest, TestAddition) {
MockCalculator mock;

EXPECT_CALL(mock, Add(1, 2))
.Times(1)
.WillOnce(::testing::Return(3));

EXPECT_EQ(mock.Add(1, 2), 3);
}

5. 自定义断言

  • 提升代码可读性,适用于复杂逻辑。

示例:

1
2
3
4
5
6
7
8
9
10
11
12
::testing::AssertionResult IsEven(int n) {
if (n % 2 == 0) {
return ::testing::AssertionSuccess();
} else {
return ::testing::AssertionFailure() << n << " is not even";
}
}

TEST(CustomAssertion, CheckEven) {
EXPECT_TRUE(IsEven(2));
EXPECT_FALSE(IsEven(3));
}

6. 测试过滤与标签

6.1 筛选测试

运行特定测试:

1
./test_binary --gtest_filter=TestSuite.TestName

运行某套件所有测试:

1
./test_binary --gtest_filter=SampleSuite.*

6.2 禁用测试

  • 使用 DISABLED_ 前缀。
1
2
3
TEST(SampleSuite, DISABLED_TestCase) {
EXPECT_EQ(1, 1);
}

7. 性能测试

  • 验证代码的性能,例如函数耗时。

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <chrono>

int TimeConsumingFunction() {
std::this_thread::sleep_for(std::chrono::milliseconds(100));
return 42;
}

TEST(PerformanceTest, HandlesTimeout) {
auto start = std::chrono::high_resolution_clock::now();
EXPECT_EQ(TimeConsumingFunction(), 42);
auto end = std::chrono::high_resolution_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
EXPECT_LE(duration, 200);
}