2026/2/19 19:04:50
网站建设
项目流程
百度站长工具平台,wordpress对空间的要求,企业seo网站推广公司,聊城高唐网站建设公司文章目录 1. GTest 是什么 2. GTest 使用2.1 TEST 宏2.2 断言 2.3 事件机制 1. GTest 是什么
GTest 是一个跨平台的 C单元测试框架#xff0c;由 google 公司发布。gtest 是为了在不同平台上为编写 C单元测试而生成的。它提供了丰富的断言、致命和非致命判断、参数化等等 2.…文章目录1. GTest 是什么2. GTest 使用2.1 TEST 宏2.2 断言2.3 事件机制1. GTest 是什么GTest 是一个跨平台的C单元测试框架由 google 公司发布。gtest 是为了在不同平台上为编写 C单元测试而生成的。它提供了丰富的断言、致命和非致命判断、参数化等等2. GTest 使用2.1 TEST 宏TEST(test_case_name,test_name)TEST_F(test_fixture,test_name)TEST主要用来创建一个简单测试 它定义了一个测试函数 在这个函数中可以使用任何 C代码并且使用框架提供的断言进行检查TEST_F主要用来进行多样测试适用于多个测试场景如果需要相同的数据配置的情况 即相同的数据测不同的行为2.2 断言GTest 中的断言的宏可以分为两类ASSERT_系列如果当前点检测失败则退出当前函数EXPECT_系列如果当前点检测失败则继续往下执行下面是经常使用的断言介绍// bool 值检查ASSERT_TRUE(参数)期待结果是trueASSERT_FALSE(参数)期待结果是false//数值型数据检查ASSERT_EQ(参数1参数2)传入的是需要比较的两个数 equalASSERT_NE(参数1参数2)notequal不等于才返回trueASSERT_LT(参数1参数2)less than小于才返回trueASSERT_GT(参数1参数2)greater than大于才返回trueASSERT_LE(参数1参数2)less equal小于等于才返回trueASSERT_GE(参数1参数2)greater equal大于等于才返回true注如果你对自动输出的错误信息不满意的话也可以通过 operator 在失败的时候打印自定义日志下面我们做个测试 实现一个求绝对值的函数 并且使用 TEST 宏及断言进行测试#includeiostream#includegtest/gtest.h/* 断言宏的使用 ASSERT_ 断言失败则退出 EXPECT_ 断言失败继续运行 注意 断言宏必须在单元测试宏函数中使用 */intabs(intx){returnx0?x:-x;}TEST(abs_test,test1){ASSERT_TRUE(abs(1)1)abs(1)1;ASSERT_TRUE(abs(-1)1);ASSERT_FALSE(abs(-2)-2);ASSERT_EQ(abs(1),abs(-1));ASSERT_NE(abs(-1),0);ASSERT_LT(abs(-1),2);ASSERT_GT(abs(-1),0);ASSERT_LE(abs(-1),2);ASSERT_GE(abs(-1),0);}intmain(intargc,char*argv[]){// 将命令行参数传递给 gtesttesting::InitGoogleTest(argc,argv);// 运行所有测试案例returnRUN_ALL_TESTS();}编译运行ltxMy-Xshell-8-Pro-Max-Ultra:~/rabbit-mq/demo/gtest$makeg -o assert assert.cc -stdc11 -lgtest ltxMy-Xshell-8-Pro-Max-Ultra:~/rabbit-mq/demo/gtest$ ./assert[]Running1testfrom1testsuite.[----------]Globaltestenvironment set-up.[----------]1testfrom abs_test[RUN]abs_test.test1[OK]abs_test.test1(1ms)[----------]1testfrom abs_test(1ms total)[----------]Globaltestenvironment tear-down[]1testfrom1testsuite ran.(1ms total)[PASSED]1test.将第一条语句改成 ASSERT_FALSE 进行错误测试ltxMy-Xshell-8-Pro-Max-Ultra:~/rabbit-mq/demo/gtest$ ./assert[]Running1testfrom1testsuite.[----------]Globaltestenvironment set-up.[----------]1testfrom abs_test[RUN]abs_test.test1 assert.cc:18: Failure Value of: abs(1)1Actual:trueExpected:falseabs(1)1[FAILED]abs_test.test1(1ms)[----------]1testfrom abs_test(1ms total)[----------]Globaltestenvironment tear-down[]1testfrom1testsuite ran.(1ms total)[PASSED]0tests.[FAILED]1test, listed below:[FAILED]abs_test.test11FAILED TEST注意ASSERT_FALSE(abs(1) 1)失败会立即终止当前测试函数abs_test.test1。后续所有断言第19-26行都不会执行。但如果使用EXPECT_FALSE(abs(1) 1)失败会继续执行当前测试函数。框架会记录失败但继续检查后面的ASSERT_TRUE、ASSERT_EQ等断言。2.3 事件机制GTest 中的事件机制是指在测试前和测试后提供给用户自行添加操作的机制而且该机制也可以让同一测试套件下的测试用例共享数据。GTest 框架中事件的结构层次测试程序一个测试程序只有一个 main 函数也可以说是一个可执行程序是一个测试程序。该级别的事件机制是在程序的开始和结束执行测试套件代表一个测试用例的集合体该级别的事件机制是在整体的测试案例开始和结束执行测试用例该级别的事件机制是在每个测试用例开始和结束都执行事件机制的最大好处就是能够为我们各个测试用例提前准备好测试环境并在测试完毕后用于销毁环境这样有个好处就是如果我们有一端代码需要进行多种不同方法的测试则可以通过测试机制在每个测试用例进行之前初始化测试环境和数据并在测试完毕后清理测试造成的影响。GTest 提供了三种常见的的事件全局事件针对整个测试程序。实现全局的事件机制需要创建一个自己的类然后继承 testing::Environment 类然后分别实现成员函数 SetUp 和 TearDown同时在 main 函数内进行调用 testing::AddGlobalTestEnvironment(new MyEnvironment);函数添加全局的事件机制#includeiostream#includegtest/gtest.h#includeunordered_map//全局事件:针对整个测试程序,提供全局事件机制,能够在测试之前配置测试环境数据,测试完毕后清理数据//先定义环境类,通过继承 testing::Environment 的派生类来完成//重写的虚函数接口 SetUp 会在测试之前被调用; TearDown 会在测试完毕后调用.classMyEnvironment:publictesting::Environment{public:virtualvoidSetUp()override{std::cout单元测试执行前的环境初始化\n;}virtualvoidTearDown()override{std::cout单元测试执行完毕后的环境清理\n;}};TEST(MyEnvironment,test1){std::cout这是单元测试1\n;}TEST(MyEnvironment,test2){std::cout这是单元测试2\n;}intmain(intargc,char*argv[]){testing::InitGoogleTest(argc,argv);testing::AddGlobalTestEnvironment(newMyEnvironment);returnRUN_ALL_TESTS();}运行结果ltxMy-Xshell-8-Pro-Max-Ultra:~/rabbit-mq/demo/gtest$makeg -o global global.cc -stdc11 -lgtest ltxMy-Xshell-8-Pro-Max-Ultra:~/rabbit-mq/demo/gtest$ ./global[]Running2tests from1testsuite.[----------]Globaltestenvironment set-up. 单元测试执行前的环境初始化[----------]2tests from MyEnvironment[RUN]MyEnvironment.test1 这是单元测试1[OK]MyEnvironment.test1(0ms)[RUN]MyEnvironment.test2 这是单元测试2[OK]MyEnvironment.test2(0ms)[----------]2tests from MyEnvironment(0ms total)[----------]Globaltestenvironment tear-down 单元测试执行完毕后的环境清理[]2tests from1testsuite ran.(0ms total)[PASSED]2tests.我们可以再来一个全局事件#includeiostream#includegtest/gtest.h#includeunordered_map// 全局事件:针对整个测试程序,提供全局事件机制,能够在测试之前配置测试环境数据,测试完毕后清理数据// 先定义环境类,通过继承 testing::Environment 的派生类来完成// 重写的虚函数接口 SetUp 会在测试之前被调用; TearDown 会在测试完毕后调用.classMyEnvironment:publictesting::Environment{public:virtualvoidSetUp()override{std::cout单元测试执行前的环境初始化\n;}virtualvoidTearDown()override{std::cout单元测试执行完毕后的环境清理\n;}};TEST(MyEnvironment,test1){std::cout这是单元测试1\n;}TEST(MyEnvironment,test2){std::cout这是单元测试2\n;}std::unordered_mapstd::string,std::stringmymap;classMyMapTest:publictesting::Environment{public:virtualvoidSetUp()override{std::cout单元测试执行前的环境初始化\n;mymap.insert(std::make_pair(hello,你好));mymap.insert(std::make_pair(bye,再见));}virtualvoidTearDown()override{std::cout单元测试执行完毕后的环境清理\n;mymap.clear();}};TEST(MyMapTest,test1){ASSERT_EQ(mymap.size(),2);mymap.erase(hello);}TEST(MyMapTest,test2){ASSERT_EQ(mymap.size(),2);}intmain(intargc,char*argv[]){testing::InitGoogleTest(argc,argv);testing::AddGlobalTestEnvironment(newMyEnvironment);testing::AddGlobalTestEnvironment(newMyMapTest);returnRUN_ALL_TESTS();}编译运行ltxMy-Xshell-8-Pro-Max-Ultra:~/rabbit-mq/demo/gtest$makeg -o global global.cc -stdc11 -lgtest ltxMy-Xshell-8-Pro-Max-Ultra:~/rabbit-mq/demo/gtest$ ./global[]Running4tests from2testsuites.[----------]Globaltestenvironment set-up. 单元测试执行前的环境初始化 单元测试执行前的环境初始化[----------]2tests from MyEnvironment[RUN]MyEnvironment.test1 这是单元测试1[OK]MyEnvironment.test1(0ms)[RUN]MyEnvironment.test2 这是单元测试2[OK]MyEnvironment.test2(0ms)[----------]2tests from MyEnvironment(0ms total)[----------]2tests from MyMapTest[RUN]MyMapTest.test1[OK]MyMapTest.test1(0ms)[RUN]MyMapTest.test2 global.cc:56: Failure Expected equality of these values: mymap.size()Which is:12[FAILED]MyMapTest.test2(1ms)[----------]2tests from MyMapTest(1ms total)[----------]Globaltestenvironment tear-down 单元测试执行完毕后的环境清理 单元测试执行完毕后的环境清理[]4tests from2testsuites ran.(1ms total)[PASSED]3tests.[FAILED]1test, listed below:[FAILED]MyMapTest.test21FAILED TEST这两个全局事件都是在单元测试之前初始化和单元测试之后清理TestSuite 事件针对一个个测试套件。测试套件的事件机制我们同样需要去创建一个类继承自 testing::Test实现两个静态函数 SetUpTestCase 和 TearDownTestCase测试套件的事件机制不需要像全局事件机制一样在 main 注册而是需要将我们平时使用的 TEST 宏改为 TEST_F 宏。SetUpTestCase() 函数是在测试套件第一个测试用例开始前执行TearDownTestCase() 函数是在测试套件最后一个测试用例结束后执行需要注意 TEST_F 的第一个参数是我们创建的类名也就是当前测试套件的名称这样在 TEST_F 宏的测试套件中就可以访问类中的成员了。#includeiostream#includegtest/gtest.h#includeunordered_map// TestSuite:测试套件/集合进行单元测试,即,将多个相关测试归入一组的方式进行测试, 为这组测试用例进行环境配置和清理// 概念: 对一个功能的验证往往需要很多测试用例测试套件就是针对一组相关测试用例进行环境配置的事件机制// 用法: 先定义环境类,继承于 testing::Test 基类, 重写两个静态函数SetUpTestCase / TearDownTestCase 进行环境的配置和清理classHashTestEnv1:publictesting::Test{public:staticvoidSetUpTestCase(){std::cout环境 1 第一个 TEST 之前调用\n;}staticvoidTearDownTestCase(){std::cout环境 1 最后一个 TEST 之后调用\n;}public:std::unordered_mapstd::string,std::stringdict;};// 注意,测试套件使用的不是 TEST 了,而是 TEST_F, 而第一个参数名称就是测试套件环境类名称// main 函数中不需要再注册环境了,而是在 TEST_F 中可以直接访问类的成员变量和成员函数TEST_F(HashTestEnv1,insert_test){std::cout环境 1,中间 insert 测试\n;dict.insert(std::make_pair(Hello,你好));dict.insert(std::make_pair(hello,你好));dict.insert(std::make_pair(雷吼,你好));autoitdict.find(hello);ASSERT_NE(it,dict.end());}TEST_F(HashTestEnv1,sizeof){std::cout环境 1,中间 size 测试\n;ASSERT_GT(dict.size(),0);}intmain(intargc,char*argv[]){testing::InitGoogleTest(argc,argv);returnRUN_ALL_TESTS();}运行结果ltxMy-Xshell-8-Pro-Max-Ultra:~/rabbit-mq/demo/gtest$makeg -o suite suite.cc -stdc11 -lgtest ltxMy-Xshell-8-Pro-Max-Ultra:~/rabbit-mq/demo/gtest$ ./suite[]Running2tests from1testsuite.[----------]Globaltestenvironment set-up.[----------]2tests from HashTestEnv1 环境1第一个 TEST 之前调用[RUN]HashTestEnv1.insert_test 环境1,中间 insert 测试[OK]HashTestEnv1.insert_test(0ms)[RUN]HashTestEnv1.sizeof 环境1,中间 size 测试 suite.cc:36: Failure Expected:(dict.size())(0), actual:0vs0[FAILED]HashTestEnv1.sizeof(0ms)环境1最后一个 TEST 之后调用[----------]2tests from HashTestEnv1(0ms total)[----------]Globaltestenvironment tear-down[]2tests from1testsuite ran.(0ms total)[PASSED]1test.[FAILED]1test, listed below:[FAILED]HashTestEnv1.sizeof1FAILED TEST能够看到在上例中有一个好处就是将数据与测试结合到同一个测试环境类中了这样与外界的耦合度更低代码也更清晰。但是同样的我们发现在两个测试用例中第二个测试用例失败了这是为什么呢这就涉及到了 TestCase 事件的机制。TestCase 事件: 针对一个个测试用例。测试用例的事件机制的创建和测试套件的基本一样不同地方在于测试用例实现的两个函数分别是 SetUp 和 TearDown, 这两个函数也不是静态函数SetUp()函数是在一个测试用例的开始前执行TearDown()函数是在一个测试用例的结束后执行也就是说在 TestSuite/TestCase 事件中每个测试用例虽然它们同用同一个事件环境类可以访问其中的资源但是本质上每个测试用例的环境都是独立的这样我们就不用担心不同的测试用例之间会有数据上的影响了保证所有的测试用例都使用相同的测试环境进行测试。#includeiostream#includegtest/gtest.h#includeunordered_map// TestCase:测试用例的单元测试,即针对每一个测试用例都使用独立的测试环境数据进行测试// 概念:它是针对测试用例进行环境配置的一种事件机制// 用法:先定义环境类,继承于 testing::Test 基类, 在环境类内重写SetUp/TearDown 接口classHashTestEnv2:publictesting::Test{public:staticvoidSetUpTestCase(){std::cout环境 2 第一个 TEST 之前被调用,进行总体环境配置\n ;}staticvoidTearDownTestCase(){std::cout环境 2 最后一个 TEST 之后被调用,进行总体环境清理\n ;}virtualvoidSetUp()override{std::cout环境 2 测试前:提前准备数据!!\n;dict.insert(std::make_pair(bye,再见));dict.insert(std::make_pair(see you,再见));}virtualvoidTearDown()override{std::cout环境 2 测试结束后:清理数据!!\n;dict.clear();}public:std::unordered_mapstd::string,std::stringdict;};TEST_F(HashTestEnv2,insert_test){std::cout环境 2,中间测试\n;dict.insert(std::make_pair(hello,你好));ASSERT_EQ(dict.size(),3);}TEST_F(HashTestEnv2,size_test){std::cout环境 2,中间 size 测试\n;autoitdict.find(hello);ASSERT_EQ(it,dict.end());ASSERT_EQ(dict.size(),2);}intmain(intargc,char*argv[]){testing::InitGoogleTest(argc,argv);RUN_ALL_TESTS();return0;}运行结果ltxMy-Xshell-8-Pro-Max-Ultra:~/rabbit-mq/demo/gtest$makeg -ocasecase.cc -stdc11 -lgtest ltxMy-Xshell-8-Pro-Max-Ultra:~/rabbit-mq/demo/gtest$ ./case[]Running2tests from1testsuite.[----------]Globaltestenvironment set-up.[----------]2tests from HashTestEnv2 环境2第一个 TEST 之前被调用,进行总体环境配置[RUN]HashTestEnv2.insert_test 环境2测试前:提前准备数据!!环境2,中间测试 环境2测试结束后:清理数据!![OK]HashTestEnv2.insert_test(0ms)[RUN]HashTestEnv2.size_test 环境2测试前:提前准备数据!!环境2,中间 size 测试 环境2测试结束后:清理数据!![OK]HashTestEnv2.size_test(0ms)环境2最后一个 TEST 之后被调用,进行总体环境清理[----------]2tests from HashTestEnv2(0ms total)[----------]Globaltestenvironment tear-down[]2tests from1testsuite ran.(0ms total)[PASSED]2tests.