当前位置: 首页 > news >正文

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

目录

  • 零、简单安装
  • 一、要求:
  • 二、编译
  • 三、使用
  • 四、demo案例
  • 参考

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

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • C++使用技巧(十四):ubuntu16.04--C++ (Cpp) PCM示例与pcm及音频算法的参考资料
  • 熊节:谁震撼了世界——第14届Jolt奖点评
  • C++使用技巧(十五):类构造函数 与 析构函数
  • 刘江:国外计算机图书月旦评(2004.4)
  • C++使用技巧(十六):智能指针
  • 聚合页面更新
  • C++使用技巧(十七):虚函数
  • C++使用技巧(十八):多肽
  • 关于“滚动的一天”潜在危险
  • C++使用技巧(十九):内存管理
  • 一个类似“作者主页平台”的地方
  • C++使用技巧(二十):再学public、protected及private用法
  • C++使用技巧(二十一):makefile编写
  • 网站设计的严重缺陷
  • C语言使用技巧(二十七):回顾strcpy函数用法
  • 《网管员必读——网络组建》(第2版)电子课件下载
  • 「面试题」如何实现一个圣杯布局?
  • 【5+】跨webview多页面 触发事件(二)
  • 【刷算法】从上往下打印二叉树
  • Android系统模拟器绘制实现概述
  • cookie和session
  • JS数组方法汇总
  • Laravel 中的一个后期静态绑定
  • MySQL用户中的%到底包不包括localhost?
  • October CMS - 快速入门 9 Images And Galleries
  • vue:响应原理
  • 将 Measurements 和 Units 应用到物理学
  • 如何在 Tornado 中实现 Middleware
  • 如何抓住下一波零售风口?看RPA玩转零售自动化
  • 双管齐下,VMware的容器新战略
  • 听说你叫Java(二)–Servlet请求
  • 微信小程序上拉加载:onReachBottom详解+设置触发距离
  • 用quicker-worker.js轻松跑一个大数据遍历
  • 远离DoS攻击 Windows Server 2016发布DNS政策
  • Mac 上flink的安装与启动
  • raise 与 raise ... from 的区别
  • 阿里云重庆大学大数据训练营落地分享
  • 树莓派用上kodexplorer也能玩成私有网盘
  • $jQuery 重写Alert样式方法
  • (12)目标检测_SSD基于pytorch搭建代码
  • (阿里云在线播放)基于SpringBoot+Vue前后端分离的在线教育平台项目
  • (附源码)小程序 交通违法举报系统 毕业设计 242045
  • (算法)硬币问题
  • (原创)Stanford Machine Learning (by Andrew NG) --- (week 9) Anomaly DetectionRecommender Systems...
  • (原創) 人會胖會瘦,都是自我要求的結果 (日記)
  • (转)3D模板阴影原理
  • (转)linux下的时间函数使用
  • (转载)虚函数剖析
  • ***php进行支付宝开发中return_url和notify_url的区别分析
  • .NET C# 使用GDAL读取FileGDB要素类
  • .NET Core 项目指定SDK版本
  • .NET Framework 3.5安装教程
  • .net FrameWork简介,数组,枚举
  • .NET 实现 NTFS 文件系统的硬链接 mklink /J(Junction)
  • .net操作Excel出错解决