google_test
Google_Test
这里学习一下相关googleTest的功能。
全文来源于:GoogleTest。笔者只进行翻译和自我理解。
安装与启动
首先我们创建一个属于自己的工作区(文件夹)。创建工作区的部分可以参考 配置 ,不同系统上略有不同但unix类型系统都差不多。windows 是异端!。
接下来撰写我们的cmake文件。首先来安装相关的库。
# 最小版本要求
cmake_minimum_required(VERSION 3.22)
# 自定义debug模式参数。
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -O0 -Wall")
# 设定编译器和C++标准
set(CMAKE_C_COMPILER "/usr/bin/clang")
set(CMAKE_CXX_COMPILER "/usr/bin/clang++")
set(CMAKE_VERBOSE_MAKEFILE ON)
set(CMAKE_CXX_STANDARD 20)
# 项目名。
project(main)
include(FetchContent)
FetchContent_Declare(
googletest
URL https://github.com/google/googletest/archive/03597a01ee50ed33e9dfd640b249b4be3799d395.zip
)
FetchContent_MakeAvailable(googletest)
set(ENV{HTTP_PROXY} "http://localhost:1080") # 没办法,gfw
然后我们编写一个简单的测试程序
#include <gtest/gtest.h>
// Demonstrate some basic assertions.
TEST(HelloTest, BasicAssertions) {
// Expect two strings not to be equal.
EXPECT_STRNE("hello", "world");
// Expect equality.
EXPECT_EQ(7 * 6, 42);
}
最后增加以下部分开启googletest。
enable_testing() # 开启测试
add_executable(main main.cpp) # 增加可执行文件和其源文件。
target_link_libraries(
main
GTest::gtest_main
) # 链接gtest动态库。
include(GoogleTest) # 包含头文件。
gtest_discover_tests(main) # 自动寻找测试项目。
从源码安装
git clone https://github.com/google/googletest.git
cd googletest/
mkdir build
cd build
cmake ..
make
sudo make install
cmake 脚本变成:
cmake_minimum_required(VERSION 3.22)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -O0 -Wall")
set(CMAKE_C_COMPILER "/usr/bin/clang")
set(CMAKE_CXX_COMPILER "/usr/bin/clang++")
set(CMAKE_VERBOSE_MAKEFILE ON)
set(CMAKE_CXX_STANDARD 20)
project(main)
enable_testing()
find_package(GTest REQUIRED)
add_executable(main main.cpp)
target_link_libraries(
main
GTest::gtest_main
)
include(GoogleTest)
gtest_discover_tests(main)
测试的一些基本原则
- 独立/可重复。
- 具有良好的结构,可以反应测试代码的结构。
- 可重用且可移植。
- 提示足够多的相关问题的信息,当测试失败的时候,可以提示该测试失败的信息,并且继续执行其他部分。
- 专注于测试的内容而非其他的一些杂项。
- 足够快。
基本概念
一般而言,googleTest将从断言开始书写。断言将会判断你的一个语句是否是真。
- 断言的结果一般有三种:
- (非致命性)失败,(致命性)失败与成功。
- 当一个致命性失败出现时,当前函数将会中断。否则程序将会继续正常运行。
测试通过断言来验证代码的行为。当测试故障或出现一个(致命性)错误断言时,测试程序中止,否则它将会成功。
一个测试组(test suites)将会包括一个或者多个测试,你可以将测试集合成多个测试组来反应测试代码的结构。多个测试在同一组中采用共享对象和子进程时,可以放入一个test fixture类中。
一个测试程序可以有多个测试组(test suites)。
断言
主要分为两种:ASSERT_*(抛出致命性错误),EXPECT_*(抛出非致命性错误)。前者需要注意可能的内存泄漏问题,因为函数将会提前终止。
我们可以通过 << 来输出错误时我们的报错信息。例如:
EXPECT_EQ(7 * 5, 42) << "The calculation result should be 42!\n";是非致命性报错,因此会继续往下执行到达程序结束。

任何的可以通过ostream输出的方式都可以通过断言输出。
简单测试
创建一个测试:
- 使用
TEST()宏来定义和命名一个测试函数。这是常用的C++的函数,并且没有返回值。 - 在这个函数中,任何合法的C++语句都可以被include,并且采用断言检查值。
- 测试结果通过断言进行决定。如果任何断言致命性失败,或者测试程序崩溃,整个测试就将会失败。否则,它将会执行结束。
TEST(TestSuiteName, TestName) {
// Test Body
}
我们可以写出一个简单的阶乘测试
#include <gtest/gtest.h>
template<class T>
T factorial(T n) {
if(n == 1 || n == 0) return 1;
else return factorial(n-1) * n;
}
TEST(MyTest, TestFactorialCase) {
// Case statement.
EXPECT_EQ(factorial(0), 1);
EXPECT_EQ(factorial(1), 1);
}
TEST(MyTest, TestFactorialNormal) {
// Some cases.
EXPECT_EQ(factorial(1), 1);
EXPECT_EQ(factorial(2), 2);
EXPECT_EQ(factorial(3), 6);
EXPECT_EQ(factorial(8), 40320);
}

Test Fixtures:多测试中采用相同数据配置
当你发现你在相同数据上写两个/多个测试,并且需要用到相同的数据配置时,可以使用test fixture,这样在不同测试中可以使用相同的对象配置。
创建一个Fixture:
- 从
testing::Test中继承一个新的类。从protected部分开始编写。 - 在类中,可以声明任意的对象。
- 如果必要,书写一个默认的构造函数
SetUp()来对每一个测试进行准备。注意拼写! - 如果必要,书写一个析构函数来销毁所有的在构造函数中分配的资源。
- 如有必要,构建子程序来告诉你的测试进行共享。
TestSuite采用如下的格式
TEST_F(TestFixtureClassName, TestName) {
// 测试函数体
}
这样我们可以编写示例函数:
#include <gtest/gtest.h>
#include <queue>
class QueueTest: public testing::Test {
protected:
std::queue<int> q0, q1, q2;
QueueTest() {
q1.push(1);
q2.push(2);
q2.push(3);
}
};
TEST_F(QueueTest, IsEmptyInitially) {
EXPECT_EQ(q0.size(), 0);
}
TEST_F(QueueTest, DequeueWorks) {
EXPECT_EQ(q0.empty(), true);
int n = q1.front();
EXPECT_EQ(n, 1);
q1.pop();
EXPECT_EQ(q1.size(), 0);
n = q2.front();
EXPECT_EQ(n, 2);
q2.pop();
EXPECT_EQ(q2.size(), 1);
}
添加main函数
我们可以将google test集成到main函数中。这样我们可以实现执行其他部分的功能。main函数的一个实例如下:
int main() {
testing::InitGoogleTest();
int status = RUN_ALL_TESTS();
return status;
}
status = 0 代表执行成功,否则其他情况将返回1.
更进一步
接下来将进入更多的技巧,例如复杂的失败信息,传递致命性失败信息,重用和提高测试集合速度,以及采用不同的flags。
更多的断言
- 显式的成功和失败。
SUCCEED(),FAIL()(致命性),ADD_FAILURE(file, line)(非致命性)。ADD_FAILURE_AT()在指定文件和行后增加非致命性信息。
- 异常断言
EXPECT/ASSERT_THROW(statement, exception_type)验证抛出特定类型的错误。
复杂分枝
采用一以下函数来提供比EXPECT_TRUE(statement)更好的消息。
testing::AssertionResult IsEven(int n) {
if ((n % 2) == 0)
return testing::AssertionSuccess();
else
return testing::AssertionFailure() << n << " is odd";
}
// bool IsEven(int n) {
// return (n % 2) == 0;
// }
浮点数比较
采用以下方式来进行简单但是比较全面的比较。
using ::testing::FloatLE;
using ::testing::DoubleLE;
// ...
EXPECT_PRED_FORMAT2(FloatLE, val1, val2);
EXPECT_PRED_FORMAT2(DoubleLE, val1, val2);
[未完待续]

浙公网安备 33010602011771号