zl程序教程

您现在的位置是:首页 >  其他

当前栏目

C++使用技巧(十三):Google-GTest测试框架的安装与使用(demo源码实现)

2023-09-14 09:15:32 时间


gtest是google公司发布的一个跨平台(Liunx、Mac OS、Windows 等) 的C++单元测试框架, 它提供了丰富的断言、致命和非致命判断、参数化、”死亡测试”等等。 ——————解决代码错误,打印错误位置,进行调试,修复bug,上线,验证代码所有逻辑都能跑到。

Test 使用断言来判断测试代码的行为:如果一个 Test 崩溃了或者出现了一个失败的断言,则该 Test 就失败了;反之,它就是成功的。

Test case (有的也叫Test suit) 包括一个或多个 Test。我们应当把 Test 打包、分组,放入 Test Case 中,以便测试代码的结构更加清晰。当一个 Test Case 中的多个 Test 需要共享对象和子程序时,我们可以把这些共享内容放入一个测试夹具(test fixture)类中。一个测试程序可以包含多个 Test Case。

零、简单安装

GTest库文件安装在/usr/local/lib/目录,头文件安装在/usr/local/include/目录.

git clone https://github.com/google/googletest.git 
cd googletest        
mkdir build       
cd build
cmake ..            
make
sudo make install    # Install in /usr/local/ by defaultgit clone https://github.com/google/googletest
cd googletest
mkdir build
cd build
cmake .. -DCMAKE_CXX_FLAGS='-std=c++11' # 不指定c++11标准会报错
make
sudo make install

参考链接:https://www.cnblogs.com/helloworldcode/p/9606838.html
https://blog.csdn.net/fengbingchun/article/details/39667571
https://blog.csdn.net/liitdar/article/details/85716608

引用:gtest 编译、安装和使用
https://blog.csdn.net/sevenjoin/article/details/89953950
gtest(google test)编译(静态库*.a和动态库*.so)与使用

googletest (gtest)的使用方法

[C++] gtest入门教程

GoogleTest框架 使用总结【二】

完成自己的Google测试框架

Google Test(GTest)使用方法和源码解析——概况

GoogleTest测试框架介绍(二)

【测试开发】使用vs code + gtest进行单元测试 - 初体验

一、要求:

  1. 安装 cmake,gcc,g++

二、编译

  1. 下载 gtest 源码包,并解压,如:/home/hdc/gtest-1.7.0;
  2. 编译 gtest 动态库,进入 gtest-1.7.0 目录,编辑 CMakeLists.txt,修改如下几行:
    10 option(BUILD_SHARED_LIBS “Build shared libraries (DLLs).” OFF)
    19 option(gtest_build_tests “Build all of gtest’s own tests.” OFF)
    21 option(gtest_build_samples “Build gtest’s sample programs.” OFF)
    将 OFF 修改为 ON,保存并退出。
  3. 创建 build 目录,并进入该目录;
  4. cmake …
  5. make
  6. ls *.so
    libgtest_dll.so libgtest_main_no_rtti.so libgtest_main_use_own_tuple.so libgtest.so
    libgtest_main_no_exception.so libgtest_main.so libgtest_no_exception.so
  7. sudo cp *.so /usr/lib/gtest
  8. cd …/include
  9. sudo cp -pr gtest /usr/include
  10. sudo chown root:root /usr/include/gtest -R
  11. sudo chmod u+w /usr/include/gtest -R
  12. sudo mkdir /usr/lib/gtest && cd /usr/lib/gtest
  13. sudo ln -s libgtest.so libgtest.so.6
  14. sudo ln -s libgtest.so libgtest.so.6.0
  15. sudo ln -s libgtest_main.so libgtest_main.so.6
  16. sudo ln -s libgtest_main.so libgtest_main.so.6.0

三、使用

  1. vim func.h
#ifndef FUNC_C
#define FUNC_C
 
 
#ifdef __cplusplus
extern "C"
{
#endif
 
 
int fac(int nInput);
 
 
#ifdef __cplusplus
}
#endif
 
 
#endif // FUNC_C
  1. vim func.c
#include "func.h"
 
 
int fac(int nInput)  
{  
    if(nInput < 0) { 
      return -1;
    }
 
    int nRev = 1;  
    for(int i = 1; i <= nInput; ++i){  
      nRev *= i;  
    }  
    return nRev;  
}
  1. vim fac_test.cpp
#include <limits>
#include "func.h"
#include "gtest/gtest.h"
  
TEST(Fac_test, input_negative){  
    EXPECT_EQ(-1, fac(-1));  
    EXPECT_EQ(-1, fac(-2));  
    EXPECT_EQ(-1, fac(-5));  
}  
  
TEST(Fac_test, input_zero){  
    EXPECT_EQ(1, fac(0));  
}  
  
TEST(Fac_test, input_positive){  
    EXPECT_EQ(1, fac(1));  
    EXPECT_EQ(2, fac(2));  
    EXPECT_EQ(6, fac(3));  
}
  1. vim Makefile
CC = gcc
CPP = g++
LINK = g++
CFLAGS = -g -Wall -Werror -Wextra -std=gnu99
CPPFLAGS = -g -Wall -Werror -Wextra
LIBS = -L/usr/lib/gtest -lgtest -lgtest_main


C__SOURCES = $(wildcard *.c)
CPPSOURCES = $(wildcard *.cpp)
OBJECTS = $(patsubst %.c, %.o, $(C__SOURCES)) $(patsubst %.cpp, %.o, $(CPPSOURCES))
TARGET = sample_unittest


first: all


%.o: %.c
    $(CC) -c $(CFLAGS) -o $@ $<


%.o: %.cpp
    $(CPP) -c $(CPPFLAGS) -o $@ $<


all: $(TARGET)


$(TARGET): $(OBJECTS)
    $(LINK) $(CPPFLAGS) $(LIBS) -o $(TARGET) $(OBJECTS)


.PHONY: clean


clean:
    rm -f $(TARGET) $(OBJECTS)


5. make
6. export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/lib/gtest
7. ./sample_unittest

四、demo案例

其他案例1:TEST() 宏的第一个参数是 Test Case 的名称,第二个参数是(隶属于第一个Test Case参数的)Test 的名称。一个测试的完整名称包括 Test Case 名称及 Test 的名称,不同 Test Case 的 Test 名称可以相同。googletest 根据 test case 对测试结果进行分组,所以一些相关的 test 应当放入同一个 test case 中。

#include "gtest/gtest.h"
 
#include "gtest/gtest.h"
 
bool IsPositive(int num) {
    return num > 0? true : false;
}
 
TEST(PositiveTest, HandlesPositiveInput) {
    EXPECT_TRUE(IsPositive(1));
}
 
TEST(PositiveTest, HandlesNegativeInput) {
    EXPECT_FALSE(IsPositive(-1));
}
 
int main(int argc, char **argv) {
    testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}

执行结果:

g++ main.cc -std=c++11 -lgtest -lpthread -o main && ./main
[==========] Running 2 tests from 1 test suite.
[----------] Global test environment set-up.
[----------] 2 tests from PositiveTest
[ RUN      ] PositiveTest.HandlesPositiveInput
[       OK ] PositiveTest.HandlesPositiveInput (0 ms)
[ RUN      ] PositiveTest.HandlesNegativeInput
[       OK ] PositiveTest.HandlesNegativeInput (0 ms)
[----------] 2 tests from PositiveTest (0 ms total)

[----------] Global test environment tear-down
[==========] 2 tests from 1 test suite ran. (0 ms total)
[  PASSED  ] 2 tests.

其他案例2:一个简单的计算

#include <gtest/gtest.h>

int add(int a, int b) { 
    return a + b; 
}
TEST(testCase, test0) { 
    EXPECT_EQ(add(8, 11), 19); 
}

int main(int argc, char **argv) {
  testing::InitGoogleTest(&argc, argv);
  int a = add(2,5);
  std::cout << "a------------>" <<a << std::endl;
  return RUN_ALL_TESTS();
}

执行结果:

g++ main.cc -std=c++11 -lgtest -lpthread -o main && ./main 
a------------>7
[==========] Running 1 test from 1 test suite.
[----------] Global test environment set-up.
[----------] 1 test from testCase
[ RUN      ] testCase.test0
[       OK ] testCase.test0 (0 ms)
[----------] 1 test from testCase (0 ms total)

[----------] Global test environment tear-down
[==========] 1 test from 1 test suite ran. (0 ms total)
[  PASSED  ] 1 test.

其他案例3:事件机制
全局事件
要实现全局事件,必须写一个类,继承testing::Environment类,实现里面的SetUp和TearDown方法。

1. SetUp()方法在所有案例执行前执行

2. TearDown()方法在所有案例执行后执行

还需要告诉gtest添加这个全局事件,我们需要在main函数中通过testing::AddGlobalTestEnvironment方法将事件挂进来,也就是说,我们可以写很多个这样的类,然后将他们的事件都挂上去。

TestSuite事件
我们需要写一个类,继承testing::Test,然后实现两个静态方法

1. SetUpTestCase() 方法在第一个TestCase之前执行

2. TearDownTestCase() 方法在最后一个TestCase之后执行

在编写测试案例时,我们需要使用TEST_F这个宏,第一个参数必须是我们上面类的名字,代表一个TestSuite。

TestCase事件
TestCase事件是挂在每个案例执行前后的,实现方式和上面的几乎一样,不过需要实现的是SetUp方法和TearDown方法:

1. SetUp()方法在每个TestCase之前执行

2. TearDown()方法在每个TestCase之后执行
#include <gtest/gtest.h>
#include <map>
#include <iostream>
using namespace std;
class Student{
public:
    Student(){
        age=0;
    }
    Student(int a){
        age=a;
    }
    void print(){
    cout<<"*********** "<<age<<" **********"<<endl;;
        }  
private:
    int age;
};
class FooEnvironment : public testing::Environment{
public:
    virtual void SetUp()
    {
        std::cout << "Foo FooEnvironment SetUP" << std::endl;
    }
    virtual void TearDown()
    {
        std::cout << "Foo FooEnvironment TearDown" << std::endl;
    }
};
static Student *s;
//在第一个test之前,最后一个test之后调用SetUpTestCase()和TearDownTestCase()
class TestMap:public testing::Test
{
public:
    static void SetUpTestCase()
    {
        cout<<"SetUpTestCase()"<<endl;
    s=new Student(23);
    }
 
    static void TearDownTestCase()
    {
    delete s;
        cout<<"TearDownTestCase()"<<endl;
    }
    void SetUp()
    {
        cout<<"SetUp() is running"<<endl;
         
    }
    void TearDown()
    {
        cout<<"TearDown()"<<endl;
    } 
};
 
TEST_F(TestMap, Test1)
 {
 
    // you can refer to s here
    s->print();
}
int main(int argc, char** argv)
{
    testing::AddGlobalTestEnvironment(new FooEnvironment);
    testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}

执行结果:

g++ main.cc -std=c++11 -lgtest -lpthread -o main && ./main 
[==========] Running 1 test from 1 test suite.
[----------] Global test environment set-up.
Foo FooEnvironment SetUP
[----------] 1 test from TestMap
SetUpTestCase()
[ RUN      ] TestMap.Test1
SetUp() is running
*********** 23 **********
TearDown()
[       OK ] TestMap.Test1 (0 ms)
TearDownTestCase()
[----------] 1 test from TestMap (0 ms total)

[----------] Global test environment tear-down
Foo FooEnvironment TearDown
[==========] 1 test from 1 test suite ran. (0 ms total)
[  PASSED  ] 1 test.

参考来源:https://blog.51cto.com/u_3078781/3286687
在这里插入图片描述

参考

https://blog.csdn.net/A_L_A_N/article/details/106952145
https://mikeblog.top/2019/01/02/googletest/
http://139.224.210.242/2021/12/09/p44_google_test_1/
https://zditect.com/article/21314020.html
https://github.com/google/googletest
https://www.daimajiaoliu.com/daima/4870d98f59003f4
https://www.daimajiaoliu.com/daima/47978427c900420
https://www.jianshu.com/p/3f374655d96b
https://www.cnblogs.com/helloworldcode/p/9606838.html
视频参考:https://www.bilibili.com/video/BV1N54y1q7mv?spm_id_from=333.337.search-card.all.click