Windows上编译GTest并执行测试用例

news2024/12/26 10:50:15

目录

  • 0 背景
  • 1 环境
  • 2 生成GTest动态库
    • 2.1 下载最新GTest库
    • 2.2 编译GTest
      • 2.2.1 cmake gtest
        • 2.2.1.1 遇到问题:target参数不对
        • 2.2.1.2 遇到问题:xxx thread 编译报错
      • 2.2.2 用VS2015编译依赖库
  • 3 依赖库部署
    • 3.1 遇到问题
  • 4 编写测试用例
  • 5 效果展示

0 背景

之前写代码一直有习惯于搭建LLT框架,作为测试防护网能够大大提升代码健壮性,有效避免修改引入,另一方面测试用例作为项目重要资产也应该有个地方可以归档,写入LLT用例里面还可以通过git上库。
当前项目中只有业务应用代码,还未有对应用例,为了后续开发以及测试方便,抽了点时间研究在windows下编译GTest并执行。

1 环境

本地项目编译/运行的相关环境如下所示:

编号名称版本
1操作系统Windows 11
2编译环境Qt 5.8
3编程语言C++14
4编译器版本VS2015 MSVC 19.0
5GTest版本V1.15.2

2 生成GTest动态库

2.1 下载最新GTest库

GTest源码可以到GitHub下载,取对应的Release版本即可。通过打开网页可以看到最新版本是1.15.2,我现在用的就是最新的。
在这里插入图片描述

如果本地配好Git环境直接可以用命令行操作方便快捷:

git clone https://github.com/google/googletest.git -b v1.15.2

如果遇到git clone链接超时可以参考这个博客进行配置,就两个命令,亲测有效。

2.2 编译GTest

2.2.1 cmake gtest

一般来说,编译常规操作如下:

mkdir build
cd build
cmake ..
make && make install

但是我在执行的过程中出现很多问题,例如在gtest默认生成是静态库而不是动态库,还有编出来的版本是x86而不是x64等等。正常来说普通方式就能够编译,由于不同环境之间差异,我本地编译一直失败,于是乎我才用gtest和gmock单独编译的方式

编译命令如下:

mkdir build
cd build
cmake -G "Visual Studio 14 2015 Win64" ..

这里我强制指定了用64位编译,是因为我Qt项目所有的编译选项都是64位的,包括其他依赖库,为了配套,我选择编译64位。
执行情况:
在这里插入图片描述
到这里就能执行成功。同样的操作对gmock进行编译。然后就能获得对应.sln文件。(这一步编译成功后,我尝试在上一层目录,即gtest、gmock同级目录下的build执行命令,也是可以成功的,但此时我的lib库已经编译成功且生效了,只能说还是走了一些弯路)

2.2.1.1 遇到问题:target参数不对

问题情况截图报错如下:
在这里插入图片描述
根据报错提示定位Cmakelist里面执行代码,发现有个参数一开始没有赋值:GOOGLETEST_VERSION,于是我在执行开端前面加上对它的赋值且进行版本打印:

set(GOOGLETEST_VERSION "v1.15.2")
message(STATUS "GOOGLETEST_VERSION: ${GOOGLETEST_VERSION}")

重新执行cmake,问题解决。

2.2.1.2 遇到问题:xxx thread 编译报错

原始问题描述有点记不清了,但是记得跟多线程有关系,这个主要是出现在编译gtest的场景下出现。gtest目录的cmakelist里面有专门的编译选项,如果项目中对多线程没有依赖,可以改成ON。
在这里插入图片描述

2.2.2 用VS2015编译依赖库

cmake执行成功后,build目录下会出现一个googletest-distribution.sln,用VS2015打开进行编译;
在这里插入图片描述
PS:如果配置管理器里面没有x64,需要手动新建。
编译成功后在lib目录下就能看到对应的依赖库啦:
在这里插入图片描述

3 依赖库部署

在Qt项目中新建一个目录,把对应的lib库文件放到里面,且在.pro文件中进行路径指定,让编译器能找到这些动态库。
PS:放在文件夹里面的不仅要有lib库,对应的dll文件也要放进去,不然会出现编译报错。dll在前面编译出来的bin目录下。
在.pro目录下添加依赖:

#头文件依赖路径
INCLUDEPATH += 本地路径/gtest/include/
#lib库
LIBS += -L本地路径/gtest/lib/ -lgmock -lgtest

如果不需要用到gmock,可以不把它加进去,根据自己项目情况实时调整。

3.1 遇到问题

令人头大的一个编译错误:error: LNK2001: 无法解析的外部符号 “class testing::internal::Mutex testing::internal::g_gmock_mutex” (?g_gmock_mutex@internal@testing@@3VMutex@12@A)
明明已经把lib库和dll库放进去了,但还是出现编译报错,网上查了资料,在这里找到了参考答案,于是乎得修改.pro文件,只需要添加一行即可解决:

DEFINES += GTEST_LINKED_AS_SHARED_LIBRARY=1

4 编写测试用例

需要先引用头文件:

#include <gtest/gtest.h>
#include <gmock/gmock.h>

如果编译报错找不到头文件,说明是头文件路径未指定或者是指定得不对,指定正确就能正常编译了。

测试框架:

class TestGTest : public ::testing::Test
{
public:
    void SetUp() override
    {
        // 初始化操作
    }

    void TearDown() override
    {
        // 结束后操作
    }
};

TEST_F(TestGTest , TestLoadCfg)
{
    // TODO:用例代码
}

如果需要对某个类的私有函数进行测试,可以考虑使用FRIEND_TEST,通过友元访问的方式,可以直接访问被测试类的私有函数和成员。当前我的项目中采用这种方式进行插桩测试。
项目中有个类需要经常调用另一个子类获取对应属性,于是乎用到gmock对这些属性进行插桩,代码框架如下:

class MockTestClient : public TestClient {
public:
    MOCK_METHOD(int, GetA, (), (const, override));
    MOCK_METHOD(int, GetB, (), (const, override));
    MOCK_METHOD(int, GetC, (), (const, override));
    MOCK_METHOD(int, GetD, (), (const, override));

    MockTestClient () = default;
    ~MockTestClient () override = default;
};

// 测试用例
TEST_F(TestGTest, TestOutPut)
{
    auto testClient = std::make_unique<MockTestClient >();
    EXPECT_CALL(*testClient , GetA()).WillOnce(::testing::Return(80));
    EXPECT_CALL(*testClient , GetB()).WillOnce(::testing::Return(1000));
    EXPECT_CALL(*testClient , GetC()).WillOnce(::testing::Return(500));
    EXPECT_CALL(*testClient , GetD()).WillOnce(::testing::Return(2000));

	// 需要自己实现
    setMockTestClient(testClient.get());

    int input = 1000;
    CheckOutPut(input);

    EXPECT_EQ(input, 1000);
}

为了跟项目业务代码做隔离,我才用编译宏隔离的方式进行,只有在编译宏UNIT_TEST生效的情况下才会进行插桩和执行用例,同时取消业务代码中多线程拉起,采用单进程方式进行测试。
在项目.pro文件中添加编译宏:

DEFINES += UNIT_TEST

5 效果展示

写完用例代码后编译调试运行,终于完成了基本用例并顺利通过:
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2083499.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

python中列表的复制亦有区别

python中 对列表的复制可以直接新变量名字等于原有列表名字&#xff0c;或者 创建新的列表从原有列表一个个复制进来。他们的区别在于下面 两个图中&#xff1a;

Codeforces 1304C - Air Conditioner(1500)

Air Conditioner 题面翻译 一个餐馆中有个空调&#xff0c;每分钟可以选择上调 1 1 1 个单位的温度或下调 1 1 1 个单位的温度&#xff0c;当然你也可以选择不变&#xff0c;初始的温度为 m m m 。 有 n n n 个食客&#xff0c;每个食客会在 t i t_i ti​ 时间点到达&am…

【maven】阿里云仓库配置

阿里云公共仓库的配置看起来有多种类型的仓库: 配置指南 我的maven是idea 自带的:D:\Program Files\JetBrains\IntelliJ IDEA 2022.3.1\plugins\maven\lib\maven3\</

突破编程 C++ 设计模式(组合模式)详尽攻略

在软件开发中&#xff0c;设计模式为程序员提供了解决特定问题的最佳实践。设计模式不仅提高了代码的可复用性和可维护性&#xff0c;还能帮助团队更好地进行协作。在这篇文章中&#xff0c;我们将深入探讨组合模式——一种结构型设计模式。 组合模式允许你将对象组合成树形结…

哪里能免费申请IP SSL证书

一、选择可信赖的证书颁发机构 首先&#xff0c;需要选择一个可信赖的证书颁发机构&#xff08;CA&#xff09;。知名的CA机构如JoySSL、Symantec、GlobalSign等提供IP SSL证书服务。这些机构能够提供符合国际标准的SSL证书&#xff0c;确保数据传输的安全性和服务器的身份验证…

Docker 安装 SqlServer

摘要&#xff1a;我们工作当中经常需要拉取多个数据库实例出来做集群&#xff0c;做测试也好&#xff0c;通过 Docker 拉取 SqlServer 镜像&#xff0c;再通过镜像运行多个容器&#xff0c;几分钟就可以创建多个实例&#xff0c;效率是相当的高。 1. docker 拉取镜像 注意&am…

C++与OpenCV联袂打造:智能视觉识别技术的实践与探索

C与OpenCV联袂打造&#xff1a;智能视觉识别技术的实践与探索 1. 环境设置与准备工作1.1 安装OpenCV和配置开发环境1.1.1 下载OpenCV1.1.2 安装OpenCVWindows系统Linux系统 1.1.3 配置OpenCV库 1.2 C编译器的选择与配置1.2.1 Windows系统1.2.2 Linux系统1.2.3 编译器配置 1.3 选…

浏览器中的开源SQL可视化工具:sqliteviz

sqliteviz&#xff1a; 在浏览器中&#xff0c;即刻开启数据可视化之旅。- 精选真开源&#xff0c;释放新价值。 概览 sqliteviz是一个专为数据可视化而设计的单页离线优先PWA&#xff0c;它利用了现代浏览器技术&#xff0c;让用户无需安装任何软件即可在本地浏览器中进行SQL…

助力外骨骼机器人动力学分析

目录 一、动力学分析 二、拉格朗日方程 三、参考文献 一、动力学分析 动力学是考虑引起运动所需要的力&#xff0c;使执行器作用的力矩或施加在操作臂上的外力使操作臂按照这个动力学方程运动。 目前机器人动力学分析中主要采用牛顿-欧拉动力学方程和拉格朗日动力学方程 […

Leetcode面试经典150题-13.罗马数字转整数

解法都在代码里&#xff0c;不懂就留言或者私信&#xff0c;这个是相对简单点的&#xff0c;感觉会在低职级面试的时候考 class Solution {/**罗马数字转整数还是比较简单的&#xff0c;基本思路&#xff1a;把罗马数字字符串转成字符数组同时创建一个int型数组&#xff0c;遍…

直线公理使初等数学一直将各异直线误为同一线 ——数集相等定义凸显初数一直将各异假R误为R

黄小宁&#xff08;通讯&#xff1a;广州市华南师大南区9-303 510631&#xff09; [摘要]任何图≌自己这一几何最起码常识凸显初等数学一直将无穷多各异直线&#xff08;平面&#xff09;误为同一线&#xff08;面&#xff09;。数集相等的定义凸显&#xff1a;初数应有几何起码…

linux文件——文件系统——文件系统深度理解、学习inode

前言&#xff1a;本篇内容讲解文件系统的细节问题。 在本篇内容中&#xff0c; 我们在学习文件系统的过程中&#xff0c; 我们可以理解inode的原理&#xff0c; 理解如何在文件系统的概念下新建文件&#xff0c; 删除文件&#xff0c; 查找文件&#xff0c; 修改文件等等问题。…

商圣集团:数字创新,引领智慧生活新篇章

在全球化经济不断演进的大潮中&#xff0c;数字经济已成为推动社会进步的关键引擎&#xff0c;重塑着我们的生产与生活模式。商圣集团&#xff0c;以服务社会、创新驱动为核心价值观&#xff0c;致力于利用数字化技术&#xff0c;为个人和企业带来高效、便捷的服务体验&#xf…

【高阶数据结构】秘法(一)——并查集:探索如何高效地管理集合

前言&#xff1a; 前面我们已经学习了简单的数据结构&#xff0c;包括栈与队列、二叉树、红黑树等等&#xff0c;今天我们继续数据结构的学习&#xff0c;但是难度上会逐渐增大&#xff0c;在高阶数据结构中我们要学习的重点是图等 目录 一、并查集的原理 二、并查集的基本操作…

嘉兴银行业绩上涨却市值下滑,新任行长背后的辛酸

撰稿|芋圆 2024年3月6日&#xff0c;秦山核电有限公司&#xff08;以下简称“泰山核电”&#xff09;在上海联合产权交易所转让其所持有的嘉兴银行股份有限公司&#xff08;下称“嘉兴银行”&#xff09;的全部股份630万股的&#xff0c;占嘉兴银行总股本的0.3272%&#xff0c…

【c++】类和对象(上)(类的定义格式、访问限定符、类域、类的实例化、对象的内存大小、this指针)

&#x1f31f;&#x1f31f;作者主页&#xff1a;ephemerals__ &#x1f31f;&#x1f31f;所属专栏&#xff1a;C 目录 前言 一、类的概念及定义 1. 类的定义格式 2. 访问限定符 二、类域 三、类的实例化--对象 1. 实例化的概念 2. 对象的内存大小 四、this指针 …

Vue——认识day02

此处接上一篇文章Vue——初识Vue开始&#xff0c;欢迎大家。 目录 1.MVVM模型 2.Object.defineproperty方法 3.数据代理简介 4.Vue中的数据代理 总结 1.MVVM模型 MVVM模型是一种软件架构模式&#xff0c;用于将用户界面&#xff08;View&#xff09;&#xff0c;业务逻辑&…

牛客周赛 Round 35 (A~G)

本次A~D较为简单&#xff0c;E是一道很好的构造题&#xff0c;FG主要就是考察组合数和约数个数 A.小红的字符串切割 思路 &#xff1a;签到题 void solve() {string s;cin>>s;int lens.size();cout<<s.substr(0,len/2)<<endl<<s.substr(len/2); }B.小…

搭建面向切面编程项目

此项目在整合Mybatis基础上修改&#xff0c;可参考主页的整合Mybatis文章 注解版本 第一步 引入maven坐标 <!-- 切面编程所需jar包--><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId>…

Chapter 04 Vue指令(下)

欢迎大家订阅【Vue2Vue3】入门到实践 专栏&#xff0c;开启你的 Vue 学习之旅&#xff01; 文章目录 前言一、指令修饰符二、v-bind对于样式操作的增强三、v-model应用于表单元素 前言 在 Vue.js 中&#xff0c;指令是带有 v- 前缀的特殊属性&#xff0c;不同属性对应不同的功…