目录
- 一.为什么要编写单元测试代码
- 二.gtest是什么
- 三.下载
- 四.使用方法
-
- [4.1 场景一](#4.1 场景一)
- [4.2 场景二](#4.2 场景二)
- [4.3 场景三](#4.3 场景三)
- 五.其他
一.为什么要编写单元测试代码
相信很多人都不喜欢编写单元测试代码,但是单元测试对我们来说真的很重要,单元测试可以暴露出我们自己的代码的内部问题,从而保证我们自己的代码的正确性,避免出现各种bug。单元测试应该覆盖我们自己的代码的全部内部逻辑。
二.gtest是什么
gtest(全称googletest)是谷歌开源的一个单元测试框架,包含很多适用于具体场景的宏,可以方便的编写单元测试代码。
三.下载
源码下载地址:GitHub仓库。
源码下载完成之后构建工程,基本构建方法:
cd googletest
mkdir build
cd build
cmake ...
可以根据需要调整构建指令,这样就可以构建出合适的工程出来,然后编译生成需要的库文件就可以了。
四.使用方法
本文讨论三种场景,给出示例代码,但是不展示效果,可以自行测试,这样理解效果更好。
示例使用的是VS2022。
如果编译时报错检测到"RuntimeLibrary"的不匹配项: 值"MTd_StaticDebug"不匹配值"MDd_DynamicDebug",原因是编译gtest库时设置的编译参数和编写单元测试代码时不一样。可以在项目属性->C/C+±>代码生成->运行库,改为一致即可。
4.1 场景一
如果需要测试的若干个case互不相关,可以使用TEST宏测试。
TEST宏的第一个参数是测试套件名,第二个参数是测试案例名,是自己填写的。一个测试套件包含若干个测试案例。
示例代码:
cpp
//main.cpp
#include<gtest/gtest.h>
int Func(int data)
{
return data;
}
TEST(TestDemo, test1)
{
int data = 10;
EXPECT_EQ(data, Func(10));
}
TEST(TestDemo, test2)
{
int data = 5;
EXPECT_EQ(data, Func(10));
}
int main(int argc, char* argv[])
{
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
4.2 场景二
如果需要测试的若干个case都具有相同的数据配置,可以使用TEST_F宏测试。
使用TEST_F宏需要先编写继承自testing::Test
的固件类,用来提供数据配置。
TEST_F宏的第一个参数是测试套件名,必须要和固件类名一致,第二个参数是测试案例名,自己填写。一个测试套件包含若干个测试案例。
示例代码:
cpp
//demo.h
#ifndef DEMO_H
#define DEMO_H
class Demo
{
public:
explicit Demo(int data) :m_data(data) {}
~Demo() noexcept = default;
int GetData()
{
return m_data;
}
private:
int m_data;
};
#endif // !DEMO_H
cpp
//test.h
#ifndef TEST_H
#define TEST_H
#include<iostream>
#include<gtest/gtest.h>
#include"demo.h"
class DemoTest : public testing::Test
{
protected:
DemoTest() :m_demo(10) {}
~DemoTest() noexcept override = default;
void SetUp() override
{
//可以在这个函数里设置数据配置
std::cout << "DemoTest::SetUp" << std::endl;
}
void TearDown() override
{
//可以在这个函数里释放资源
std::cout << "DemoTest::TearDown" << std::endl;
}
protected:
Demo m_demo;
};
#endif // !TEST_H
cpp
//test.cpp
#include"test.h"
TEST_F(DemoTest, test1)
{
int data = 10;
EXPECT_EQ(data, m_demo.GetData());
}
TEST_F(DemoTest, test2)
{
int data = 5;
EXPECT_EQ(data, m_demo.GetData());
}
cpp
//main.cpp
#include<gtest/gtest.h>
int main(int argc, char* argv[])
{
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
4.3 场景三
如果同一个测试需要不同的输入参数,可以使用TEST_P宏测试。
使用TEST_P宏需要先编写继承自testing::TestWithParam<type>
的固件类,<type>
就是想要传入的参数的类型。
TEST_P宏的第一个参数是测试套件名,必须要和固件类名一致,第二个参数是测试案例名,自己填写。一个测试套件包含若干个测试案例。
示例代码:
cpp
//test.h
#ifndef TEST_H
#define TEST_H
#include<iostream>
#include<gtest/gtest.h>
class DemoTest : public testing::TestWithParam<int>
{
protected:
DemoTest() = default;
~DemoTest() noexcept override = default;
void SetUp() override
{
//可以在这个函数里设置数据配置
std::cout << "DemoTest::SetUp" << std::endl;
}
void TearDown() override
{
//可以在这个函数里释放资源
std::cout << "DemoTest::TearDown" << std::endl;
}
};
#endif // !TEST_H
cpp
//test.cpp
#include"test.h"
TEST_P(DemoTest, test1)
{
int data = 5;
EXPECT_EQ(data, GetParam());
}
TEST_P(DemoTest, test2)
{
int data = 10;
EXPECT_EQ(data, GetParam());
}
INSTANTIATE_TEST_SUITE_P(DEMO, DemoTest, testing::Values(0, 5, 10));
cpp
//main.cpp
#include<gtest/gtest.h>
int main(int argc, char* argv[])
{
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
五.其他
-
Linux下使用方法类似。
-
可以在官方文档查看更多用法。
-
可以使用gmock进行打桩。