1.简介
GoogleTest是由Google开发的一个C++测试框架,支持Linux、Windows和macOS操作系统,使用Bazel或CMake构建工具。
项目主页:GitHub - google/googletest: GoogleTest - Google Testing and Mocking Framework
官方文档:GoogleTest User’s Guide | GoogleTest
2.windows使用
准备
将下载的googletest解压,将googletest文件夹复制到项目目录下
gtest_test
│ .gitattributes
│ .gitignore
│ CMakeLists.txt
│ LICENSE.txt
│ README.md
│
├─mytest
│ CMakeLists.txt
│ test_add.cpp
│ test_multiply.cpp
├─src
│ │
│ └─add
│ add.txt
│ add.cpp
│ CMakeLists.h
│
└─googletest
在主目录下的CMakeLists.txt中引入googletest路径
#引入googletest子模块
add_subdirectory(googletest)
#引入googletest子模块的头文件,方便其他模块include
include_directories(googletest/include)
添加测试对象
在src文件中添加测试对象如下:
//add.h
#pragma once
int add(int x,int y);
//add.cpp
#include "add.h"
int add(int x,int y)
{
return x + y;
}
//add文件夹中CMakeLists.txt
aux_source_directory(. ADD_SRC)
message("ADD_SRC: ${ADD_SRC}")
add_library(add STATIC ${ADD_SRC})
target_include_directories(add INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})
将各部分作为子模块引入到项目中
在根目录CMakeLists.txt添加内容
#根目录CMakeLists.txt
cmake_minimum_required(VERSION 3.11)
project(GtestTest VERSION 0.1 LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
#引入各子模块
add_subdirectory(src/add)
#使能测试
enable_testing()
#该选项对于msvc编译器很重要
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
#引入googletest子模块
add_subdirectory(googletest)
#引入googletest子模块的头文件,方便其他模块include
include_directories(googletest/include)
编写测试代码
//test_add.cpp
#include "gtest/gtest.h"
#include "add.h"
//其中第一个参数是测试套件名称,第二个参数是测试用例名称,二者都必须是合法的C++标识符,并且不应该包含下划线。
TEST(TestAdd, test_add_1) {
int result = add(22, 33);
EXPECT_EQ(result, 55);
}
TEST(TestAdd, test_add_2) {
int result = add(22, 11);
EXPECT_EQ(result, 33);
}
mytest文件夹中添加CMakeLists.txt
//mytest文件夹中CMakeLists.txt
add_executable(test_add test_add.cpp)
target_link_libraries(test_add add gtest gtest_main)
add_test(NAME test_add COMMAND test_add)
根目录CMakeLists.txt引入测试
#根目录CMakeLists.txt
cmake_minimum_required(VERSION 3.11)
project(GtestTest VERSION 0.1 LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
#引入各子模块
add_subdirectory(src/app)
#引入测试
add_subdirectory(mytest)
#使能测试
enable_testing()
#该选项对于msvc编译器很重要
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
#引入googletest子模块
add_subdirectory(googletest)
#引入googletest子模块的头文件,方便其他模块include
include_directories(googletest/include)
运行测试
在QT工具中右击项目,选择"build",构建完毕后,在项目路径下会生成一个文件,进入生成的文件目录->在文件夹的路径里输入powershell,进入窗口->执行ctest -V命令
3.断言
GoogleTest断言是类似于函数调用的宏,用于测试类或函数的行为。当断言失败时,GoogleTest将打印断言所在的源文件、行数以及错误信息。
每个断言都有两种版本:
ASSERT_*版本的失败是致命失败,当检查点失败时,退出当前函数;
EXPECT_*版本的失败是非致命失败,当检查点失败时,继续往下执行。
GoogleTest提供了一组断言,用于检查布尔值、使用比较运算符比较两个值、比较字符串以及浮点数等。所有断言都定义在头文件<gtest/gtest.h>中。
常用断言如下(每个断言都有对应的ASSERT_*版本,这里省略):
断言 | 验证条件 | |
---|---|---|
布尔值检查: | ||
EXPECT_TRUE(condition) | ASSERT_TRUE(condition) | condition 为真 |
EXPECT_FALSE(condition) | ASSERT_FALSE(condition) | condition 为假 |
数值类型检查: | ||
EXPECT_EQ(val1, val2) | ASSERT_EQ(val1, val2) | val1 == val2 |
EXPECT_NE(val1, val2) | ASSERT_NE(val1, val2) | val1 != val2 |
EXPECT_LT(val1, val2) | ASSERT_LT(val1, val2) | val1 < val2 |
EXPECT_LE(val1, val2) | ASSERT_LE(val1, val2) | val1 <= val2 |
EXPECT_GT(val1, val2) | ASSERT_GT(val1, val2) | val1 > val2 |
EXPECT_GE(val1, val2) | ASSERT_GE(val1, val2) | val1 >= val2 |
字符串类型检查: | ||
EXPECT_STREQ(str1, str2) | ASSERT_STREQ(str1, str2) | C字符串str1 和str2 相等 |
EXPECT_STRNE(str1, str2) | ASSERT_STRNE(str1, str2) | C字符串str1 和str2 不相等 |
EXPECT_STRCASEEQ(str1, str2) | ASSERT_STRCASEEQ(str1, str2) | C字符串str1 和str2 相等,忽略大小写 |
EXPECT_STRCASENE(str1, str2) | ASSERT_STRCASENE(str1, str2) | C字符串str1 和str2 不相等,忽略大小写 |
浮点数检查: | ||
EXPECT_FLOAT_EQ(val1, val2) | ASSERT_FLOAT_EQ(val1, val2) | 两个float 值val1 和val2 近似相等 |
EXPECT_DOUBLE_EQ(val1, val2) | ASSERT_DOUBLE_EQ(val1, val2) | 两个double 值val1 和val2 近似相等 |
数值差检查: | ||
EXPECT_NEAR(val1, val2, abs_error) | ASSERT_NEAR(val1, val2, abs_error) | val1 和val2 之差的绝对值不超过abs_error |
返回成功或失败: | ||
EXPECT_THROW(statement, exception_type) | ASSERT_THROW(statement, exception_type) | statement 抛出exception_type 类型的异常 |
EXPECT_ANY_THROW(statement) | ASSERT_ANY_THROW(statement) | statement 抛出任何类型的异常 |
EXPECT_NO_THROW(statement) | ASSERT_NO_THROW(statement) | statement 不抛出任何异常 |
数值匹配检查: | ||
EXPECT_THAT(val, matcher) | ASSERT_THAT(val, matcher) | val 满足匹配器matcher |
完整参考列表:Assertions Reference | GoogleTest
4.测试宏
TEST 宏
说明:该宏定义用来测试其内部代码,其内部断言决定最终的测试结果。
TEST(TestSuiteName, TestName) {
... statements ...
}
用途:针对多个用例之间不需要进行数据共用的测试场景。
示例:
int add(int a, int b) {
return a + b;
}
TEST(TEST_ADD, UNSIGNED_INT_VALUE) {
int result = add(100, 200);
EXPECT_EQ(result, 300);
result = add(200, 300);
EXPECT_NE(result, 400);
}
TEST(TEST_ADD, NEGATIVE_INT_VALUE) {
int result = add(-100, -200);
EXPECT_EQ(result, -300);
result = add(-200, -300);
EXPECT_NE(result, -400);
}
TEST_F 宏
说明:该宏定义用来对 TestFixtureName 类进行多样测试。
使用方法:
TEST_F(TestFixtureName, TestName) {
... statements ...
}
用途:针对多个用例之间需要进行数据共用的测试场景,用于多样测试,也有助于简化测试代码。
使用示例:
class Student {
public:
Student(int id, std::string name): id_(id), name_(name) {};
~Student() = default;
void SetAge(int age) { age_ = age; }
int GetAge() const { return this->age_; }
void SetScore(int score) { score_ = score; }
int GetScore() const { return this->score_; }
private:
int id_;
std::string name_;
int age_;
int score_;
};
class StudentTest : public testing::Test {
protected:
void SetUp() override {
student = new Student(1234, "Tom");
}
void TearDown() override {
delete student;
}
Student* student;
};
TEST_F(StudentTest, SET_AGE_TEST) {
student->SetAge(16);
int age = student->GetAge();
EXPECT_EQ(age, 16);
}
TEST_F(StudentTest, SET_SCORE_TEST) {
student->SetScore(99);
int score = student->GetScore();
ASSERT_EQ(score, 99);
}
int main() {
testing::InitGoogleTest();
return RUN_ALL_TESTS();
}
TEST_P 宏
说明:该宏定义用来参数化测试。
使用方式:
TEST_P(TestFixtureName, TestName) {
... statements ...
}
用途:当待测试方法的行为取决于传入的参数时,而且这些参数的不同组合有多种, 而你又不想为此写多个类似的 test case 时,可以用参数化测试。
示例:
struct TestData {
int a;
int b;
int result;
char type;
};
class CalculateTest : public ::testing::TestWithParam<TestData> {
protected:
void checkData() {
int a = GetParam().a;
int b = GetParam().b;
int result = GetParam().result;
switch (GetParam().type) {
case '+':
EXPECT_EQ(a + b, result);
break;
case '-':
EXPECT_EQ(a - b, result);
break;
case '*':
EXPECT_EQ(a * b, result);
break;
case '/':
EXPECT_EQ(a / b, result);
break;
default:
break;
}
}
};
TEST_P(CalculateTest, Test) {
checkData();
}
INSTANTIATE_TEST_SUITE_P(TestMyClassParams,
CalculateTest,
::testing::Values(
TestData{100, 200, 300, '+'},
TestData{20, 5, 15, '-'},
TestData{5, 6, 30, '*'},
TestData{8, 2, 3, '/'}
));
int main() {
testing::InitGoogleTest();
return RUN_ALL_TESTS();
}