对于Linux系统
# 安装编译依赖
sudo apt-get install build-essential cmake libgtest-dev
# 编译安装
cd /usr/src/gtest
sudo cmake CMakeLists.txt
sudo make
sudo cp *.a /usr/lib
CMake集成示例
cmake_minimum_required(VERSION 3.14)
project(MyTests)
find_package(GTest REQUIRED)
add_executable(runTests test.cpp)
target_link_libraries(runTests GTest::GTest GTest::Main)
创建test.cpp:
#include
TEST(MyFirstTest, BasicAssertion) {
EXPECT_EQ(2+2, 4); // 期望相等
ASSERT_TRUE(1 < 2); // 断言为真
}
int main(int argc, char **argv) {
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
编译运行:
mkdir build && cd build
cmake .. && make
./runTests
基本断言
ASSERT_TRUE(condition); // 致命断言
EXPECT_FALSE(condition); // 非致命断言
值比较
EXPECT_EQ(val1, val2); // ==
ASSERT_NE(val1, val2); // !=
EXPECT_LT(val1, val2); // <
ASSERT_LE(val1, val2); // <=
字符串比较
ASSERT_STREQ(str1, str2); // C字符串相等
EXPECT_STRCASEEQ(str1, str2); // 忽略大小写
创建可复用的测试环境:
class VectorTest : public ::testing::Test {
protected:
void SetUp() override {
vec.push_back(1);
vec.push_back(2);
}
void TearDown() override {
vec.clear();
}
std::vector<int> vec;
};
TEST_F(VectorTest, SizeTest) {
ASSERT_EQ(vec.size(), 2);
}
TEST_F(VectorTest, CapacityTest) {
EXPECT_GE(vec.capacity(), 2);
}
使用不同参数运行相同测试逻辑:
class NumberTest : public ::testing::TestWithParam<int> {};
INSTANTIATE_TEST_SUITE_P(EvenNumbers, NumberTest,
::testing::Values(2, 4, 6, 8));
TEST_P(NumberTest, IsEven) {
int num = GetParam();
ASSERT_EQ(num % 2, 0);
}
异常断言
TEST(ExceptionTest, ThrowTest) {
EXPECT_THROW({
throw std::runtime_error("error");
}, std::runtime_error);
}
浮点数比较
ASSERT_DOUBLE_EQ(1.0000001, 1.0); // 4ULP精度
EXPECT_NEAR(1.0, 1.0001, 0.001); // 绝对误差
死亡测试(验证程序崩溃)
TEST(DeathTest, InvalidAccess) {
int* ptr = nullptr;
EXPECT_DEATH(*ptr = 1, ".*");
}
创建模拟对象:
#include
class Database {
public:
virtual ~Database() = default;
virtual int query(const std::string&) = 0;
};
class MockDB : public Database {
public:
MOCK_METHOD(int, query, (const std::string&), (override));
};
TEST(DatabaseTest, QueryTest) {
MockDB db;
EXPECT_CALL(db, query("test"))
.WillOnce(::testing::Return(42));
ASSERT_EQ(db.query("test"), 42);
}
测试命名规范:TestSuiteName.TestCaseName
每个测试保持独立,不依赖执行顺序
使用夹具减少重复代码
断言失败信息增强:
ASSERT_EQ(a, b) << "a=" << a << ", b=" << b;
./runTests --gtest_filter=TestSuite.* # 运行指定测试
./runTests --gtest_repeat=1000 --gtest_break_on_failure # 重复测试
类型参数化测试:
template <typename T>
class TypedTest : public ::testing::Test {};
TYPED_TEST_SUITE_P(TypedTest);
TYPED_TEST_P(TypedTest, Size) {
TypeParam vec;
EXPECT_EQ(vec.size(), 0);
}
REGISTER_TYPED_TEST_SUITE_P(TypedTest, Size);
using MyTypes = ::testing::Types<std::vector<int>, std::list<float>>;
INSTANTIATE_TYPED_TEST_SUITE_P(My, TypedTest, MyTypes);
时间测量
TEST(TimingTest, FastOperation) {
EXPECT_EXIT({
// 被测代码
}, ::testing::ExitedWithCode(0), "")
<< "Operation took too long";
}
示例GitLab CI配置:
test_job:
stage: test
script:
- mkdir build
- cd build
- cmake ..
- make
- ./runTests --gtest_output="xml:test_results.xml"
artifacts:
reports:
junit: build/test_results.xml
学习资源:
官方文档:https://google.github.io/googletest/
GitHub仓库:https://github.com/google/googletest
高级技巧:https://chromium.googlesource.com/external/github.com/google/googletest/+/HEAD/docs/advanced.md