如何利用gtest编写C++单元测试代码

农民  论坛元老 | 2024-11-10 14:10:39 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 1023|帖子 1023|积分 3069

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
一.为什么要编写单元测试代码

相信许多人都不喜好编写单元测试代码,但是单元测试对我们来说真的很重要,单元测试可以暴暴露我们本身的代码的内部题目,从而保证我们本身的代码的正确性,避免出现各种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宏的第一个参数是测试套件名,第二个参数是测试案例名,是本身填写的。一个测试套件包含多少个测试案例。
示例代码:
  1. //main.cpp
  2. #include<gtest/gtest.h>
  3. int Func(int data)
  4. {
  5.         return data;
  6. }
  7. TEST(TestDemo, test1)
  8. {
  9.         int data = 10;
  10.         EXPECT_EQ(data, Func(10));
  11. }
  12. TEST(TestDemo, test2)
  13. {
  14.         int data = 5;
  15.         EXPECT_EQ(data, Func(10));
  16. }
  17. int main(int argc, char* argv[])
  18. {
  19.         testing::InitGoogleTest(&argc, argv);
  20.         return RUN_ALL_TESTS();
  21. }
复制代码
4.2 场景二

如果需要测试的多少个case都具有相同的数据设置,可以利用TEST_F宏测试。
利用TEST_F宏需要先编写继承自testing::Test的固件类,用来提供数据设置。
TEST_F宏的第一个参数是测试套件名,必须要和固件类名同等,第二个参数是测试案例名,本身填写。一个测试套件包含多少个测试案例。
示例代码:
  1. //demo.h
  2. #ifndef DEMO_H
  3. #define DEMO_H
  4. class Demo
  5. {
  6. public:
  7.         explicit Demo(int data) :m_data(data) {}
  8.         ~Demo() noexcept = default;
  9.         int GetData()
  10.         {
  11.                 return m_data;
  12.         }
  13. private:
  14.         int m_data;
  15. };
  16. #endif // !DEMO_H
复制代码
  1. //test.h
  2. #ifndef TEST_H
  3. #define TEST_H
  4. #include<iostream>
  5. #include<gtest/gtest.h>
  6. #include"demo.h"
  7. class DemoTest : public testing::Test
  8. {
  9. protected:
  10.         DemoTest() :m_demo(10) {}
  11.         ~DemoTest() noexcept override = default;
  12.         void SetUp() override
  13.         {
  14.                 //可以在这个函数里设置数据配置
  15.                 std::cout << "DemoTest::SetUp" << std::endl;
  16.         }
  17.         void TearDown() override
  18.         {
  19.                 //可以在这个函数里释放资源
  20.                 std::cout << "DemoTest::TearDown" << std::endl;
  21.         }
  22. protected:
  23.         Demo m_demo;
  24. };
  25. #endif // !TEST_H
复制代码
  1. //test.cpp
  2. #include"test.h"
  3. TEST_F(DemoTest, test1)
  4. {
  5.         int data = 10;
  6.         EXPECT_EQ(data, m_demo.GetData());
  7. }
  8. TEST_F(DemoTest, test2)
  9. {
  10.         int data = 5;
  11.         EXPECT_EQ(data, m_demo.GetData());
  12. }
复制代码
  1. //main.cpp
  2. #include<gtest/gtest.h>
  3. int main(int argc, char* argv[])
  4. {
  5.         testing::InitGoogleTest(&argc, argv);
  6.         return RUN_ALL_TESTS();
  7. }
复制代码
4.3 场景三

如果同一个测试需要差别的输入参数,可以利用TEST_P宏测试。
利用TEST_P宏需要先编写继承自testing::TestWithParam<type>的固件类,<type>就是想要传入的参数的类型。
TEST_P宏的第一个参数是测试套件名,必须要和固件类名同等,第二个参数是测试案例名,本身填写。一个测试套件包含多少个测试案例。
示例代码:
  1. //test.h
  2. #ifndef TEST_H
  3. #define TEST_H
  4. #include<iostream>
  5. #include<gtest/gtest.h>
  6. class DemoTest : public testing::TestWithParam<int>
  7. {
  8. protected:
  9.         DemoTest() = default;
  10.         ~DemoTest() noexcept override = default;
  11.         void SetUp() override
  12.         {
  13.                 //可以在这个函数里设置数据配置
  14.                 std::cout << "DemoTest::SetUp" << std::endl;
  15.         }
  16.         void TearDown() override
  17.         {
  18.                 //可以在这个函数里释放资源
  19.                 std::cout << "DemoTest::TearDown" << std::endl;
  20.         }
  21. };
  22. #endif // !TEST_H
复制代码
  1. //test.cpp
  2. #include"test.h"
  3. TEST_P(DemoTest, test1)
  4. {
  5.         int data = 5;
  6.         EXPECT_EQ(data, GetParam());
  7. }
  8. TEST_P(DemoTest, test2)
  9. {
  10.         int data = 10;
  11.         EXPECT_EQ(data, GetParam());
  12. }
  13. INSTANTIATE_TEST_SUITE_P(DEMO, DemoTest, testing::Values(0, 5, 10));
复制代码
  1. //main.cpp
  2. #include<gtest/gtest.h>
  3. int main(int argc, char* argv[])
  4. {
  5.         testing::InitGoogleTest(&argc, argv);
  6.         return RUN_ALL_TESTS();
  7. }
复制代码
五.其他


  • Linux下利用方法类似。
  • 可以在官方文档查看更多用法。
  • 可以利用gmock进行打桩。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

农民

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表