Google Test Ubuntu 完整验证指南
一、环境安装
1.1 安装依赖
sudo apt-get update
sudo apt-get install -y build-essential cmake libgtest-dev git
1.2 编译 gtest 库(重要!)
libgtest-dev 只安装源码,需要手动编译:
cd /usr/src/gtest
sudo cmake CMakeLists.txt
sudo make
sudo cp *.a /usr/lib
或者使用 CMake FetchContent(推荐,无需系统安装)
二、项目结构
gtest_template_test/
├── CMakeLists.txt
├── include/
│ └── calculator.hpp # 被测试的模板类
├── src/
│ └── main.cpp # 可选的主程序
└── tests/
└── test_calculator.cpp # 测试代码
三、被测试的模板类(非虚接口)
include/calculator.hpp
ifndef CALCULATOR_HPP
define CALCULATOR_HPP
include
include
// 模板类 - 非虚接口(编译时多态)
template
class Calculator {
public:
// 非虚成员函数
T add(T a, T b) const {
return a + b;
}
T subtract(T a, T b) const {
return a - b;
}
T multiply(T a, T b) const {
return a * b;
}
T divide(T a, T b) const {
if (b == T{}) {
throw std::invalid_argument("Division by zero");
}
return a / b;
}
// 模板成员函数
template
T accumulate(const U* begin, const U* end, T init) const {
T result = init;
for (const U* ptr = begin; ptr != end; ++ptr) {
result = add(result, static_cast(*ptr));
}
return result;
}
};
// 模板特化示例
template
class Calculator {
public:
const char* add(const char* a, const char* b) const {
return "string_concat_not_supported";
}
};
endif // CALCULATOR_HPP
四、测试代码
tests/test_calculator.cpp
include
include "calculator.hpp"
include
include
include
// ============================================
// 测试夹具(Test Fixture)- 用于模板测试
// ============================================
template
class CalculatorTest : public ::testing::Test {
protected:
Calculator calc;
void SetUp() override {
// 每个测试前执行
}
void TearDown() override {
// 每个测试后执行
}
};
// 定义测试类型列表
using TestTypes = ::testing::Types;
TYPED_TEST_SUITE(CalculatorTest, TestTypes);
// ============================================
// 类型化测试(Typed Tests)
// ============================================
TYPED_TEST(CalculatorTest, AddTest) {
TypeParam result = this->calc.add(TypeParam{2}, TypeParam{3});
EXPECT_EQ(TypeParam{5}, result);
}
TYPED_TEST(CalculatorTest, SubtractTest) {
TypeParam result = this->calc.subtract(TypeParam{10}, TypeParam{4});
EXPECT_EQ(TypeParam{6}, result);
}
TYPED_TEST(CalculatorTest, MultiplyTest) {
TypeParam result = this->calc.multiply(TypeParam{3}, TypeParam{4});
EXPECT_EQ(TypeParam{12}, result);
}
TYPED_TEST(CalculatorTest, DivideTest) {
TypeParam result = this->calc.divide(TypeParam{20}, TypeParam{4});
EXPECT_EQ(TypeParam{5}, result);
}
TYPED_TEST(CalculatorTest, DivideByZeroThrows) {
EXPECT_THROW(this->calc.divide(TypeParam{10}, TypeParam{0}),
std::invalid_argument);
}
// ============================================
// 非模板类的普通测试
// ============================================
TEST(CalculatorTest, AccumulateFunction) {
Calculator calc;
std::vector numbers = {1, 2, 3, 4, 5};
int result = calc.accumulate(numbers.data(),
numbers.data() + numbers.size(),
0);
EXPECT_EQ(15, result);
}
// ============================================
// 参数化测试(Parameterized Tests)
// ============================================
class ParameterizedCalcTest : public ::testing::TestWithParam> {
protected:
Calculator calc;
};
TEST_P(ParameterizedCalcTest, AddParameterized) {
auto [a, b, expected] = GetParam();
EXPECT_EQ(expected, calc.add(a, b));
}
INSTANTIATE_TEST_SUITE_P(
AdditionCases,
ParameterizedCalcTest,
::testing::Values(
std::make_tuple(1, 2, 3),
std::make_tuple(10, 20, 30),
std::make_tuple(-5, 5, 0),
std::make_tuple(100, 200, 300)
)
);
// ============================================
// 浮点数比较测试
// ============================================
TEST(FloatCalculatorTest, FloatingPointComparison) {
Calculator calc;
double result = calc.divide(1.0, 3.0);
EXPECT_DOUBLE_EQ(0.3333333333333333, result);
EXPECT_NEAR(0.3333, result, 0.0001); // 允许误差
}
// ============================================
// 死亡测试(Death Test)- 验证程序崩溃
// ============================================
TEST(DeathTest, DivisionByZeroCrash) {
// 注意:死亡测试需要特殊编译标志
Calculator calc;
// EXPECT_DEATH(calc.divide(10, 0), ".*"); // 需要启用
}
// ============================================
// Main 函数
// ============================================
int main(int argc, char **argv) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
五、CMakeLists.txt 配置
CMakeLists.txt
cmake_minimum_required(VERSION 3.14)
project(GTestTemplateTest LANGUAGES CXX)
C++ 标准
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
方法1: 使用系统安装的 gtest
find_package(GTest REQUIRED)
include_directories({GTEST_INCLUDE_DIRS})
方法2: 使用 FetchContent(推荐,无需系统安装)
include(FetchContent)
FetchContent_Declare(
googletest
GIT_REPOSITORY https://github.com/google/googletest.git
GIT_TAG v1.14.0
)
FetchContent_MakeAvailable(googletest)
包含目录
include_directories({CMAKE_SOURCE_DIR}/include)
测试可执行文件
add_executable(run_tests tests/test_calculator.cpp)
链接 gtest
target_link_libraries(run_tests
GTest::gtest
GTest::gtest_main
pthread
)
启用测试
enable_testing()
add_test(NAME TemplateTests COMMAND run_tests)
编译选项(启用死亡测试需要)
target_compile_definitions(run_tests PRIVATE GTEST_HAS_DEATH_TEST=1)
六、编译与运行
6.1 创建构建目录并编译
mkdir build && cd build
cmake ...
make -j$(nproc)
6.2 运行测试
运行所有测试
./run_tests
运行特定测试套件
./run_tests --gtest_filter="CalculatorTest.*"
运行类型化测试
./run_tests --gtest_filter=TypedTest"
运行参数化测试
./run_tests --gtest_filter=Parameterized"
列出所有测试
./run_tests --gtest_list_tests
输出 XML 报告
./run_tests --gtest_output=xml:test_report.xml
6.3 预期输出示例
\] Running 15 tests from 4 test suites. \[----------\] Global test environment set-up. \[----------\] 5 tests from CalculatorTest/0, where TypeParam = int \[ RUN \] CalculatorTest/0.AddTest \[ OK \] CalculatorTest/0.AddTest (0 ms) \[ RUN \] CalculatorTest/0.SubtractTest \[ OK \] CalculatorTest/0.SubtractTest (0 ms) ... \[----------\] 4 tests from AdditionCases/ParameterizedCalcTest \[ RUN \] AdditionCases/ParameterizedCalcTest.AddParameterized/0 \[ OK \] AdditionCases/ParameterizedCalcTest.AddParameterized/0 (0 ms) ... \[\] 15 tests from 4 test suites ran. (2 ms total) \[ PASSED \] 15 tests. 七、关键要点总结 特性 说明 非虚模板接口 使用 TYPED_TEST_SUITE 进行类型化测试 测试夹具 模板类 CalculatorTest 继承 ::testing::Test 参数化测试 TestWithParam + INSTANTIATE_TEST_SUITE_P 断言类型 EXPECT(继续执行)vs ASSERT_(终止) 浮点比较 EXPECT_DOUBLE_EQ / EXPECT_NEAR 异常测试 EXPECT_THROW CMake 集成 推荐 FetchContent 方式 八、常见问题解决 问题1: 找不到 gtest 库 解决: 使用 FetchContent 或手动编译 /usr/src/gtest 问题2: 链接错误 undefined reference 解决: 确保链接 pthread: target_link_libraries(... pthread) 问题3: 死亡测试不可用 解决: 编译时添加 -DGTEST_HAS_DEATH_TEST=1 问题4: 模板测试不编译 解决: 确保测试代码中包含完整模板定义(头文件) 这个完整示例涵盖了 Ubuntu 下 gtest 的安装、CMake 集成、模板类非虚接口测试的所有关键场景。您可以直接复制使用!