C++自动化测试:GTest 与 GitLab CI/CD 的完美融合
在现代软件开发中,自动化测试是保证代码质量和稳定性的关键手段。对于C++项目而言,自动化测试尤为重要,它能有效捕捉代码中的潜在缺陷,提高代码的可维护性和可靠性。本文将重点介绍如何在C++项目中结合使用Google Test(GTest)和GitLab CI/CD,特别是通过提供详细的脚本示例,展示如何实现高效的自动化测试流程。
一、GTest 简介
Google Test(GTest)是Google开发的一个C++测试框架,以其跨平台兼容性、丰富的断言宏、易于使用以及强大的功能而广受欢迎。GTest支持多种测试类型,包括单元测试、异常测试、死亡测试等,并且提供了灵活的测试套件和测试用例管理机制,使得编写和维护测试代码变得简单高效。
二、GitLab CI/CD 流水线概述
GitLab CI/CD流水线是一个强大的自动化部署和测试工具,它允许开发者在代码提交时自动执行一系列任务。流水线通常分为以下几个阶段:
-
构建(build)阶段
在 GitLab CI/CD 流水线的构建阶段,主要任务是将 C++ 项目的代码进行编译和构建,生成可执行文件或库。这个阶段为后续的测试和部署阶段提供了基础。通过将源代码转化为可执行的形式,确保代码可以在不同的环境中运行。构建阶段的作用在于,它能够及时发现编译错误和依赖问题,避免在后续阶段浪费时间。如果构建阶段出现问题,可以快速定位并解决,提高开发效率。 -
测试(test)阶段
在测试阶段,使用 GTest 具有重要意义。GTest(Google Test)是一个强大的 C++ 测试框架,它提供了丰富的断言和测试工具,可以对 C++ 项目进行高效的单元测试、集成测试等。在这个阶段,通过运行各种测试用例,可以确保代码的功能正常,及时发现潜在的问题。使用 GTest 可以提高测试的覆盖率和准确性,增强代码的可靠性。同时,结合 GitLab CI/CD,可以自动执行测试,提高测试的效率和一致性。在测试阶段,可以根据项目的需求,编写不同类型的测试用例,如功能测试、性能测试等,以全面验证代码的质量。 -
部署(deploy)阶段
部署阶段的流程通常包括将构建好的代码部署到生产环境或其他目标环境中。首先,需要确保构建和测试阶段都成功完成,没有出现错误。然后,可以使用自动化工具或脚本来将代码部署到目标环境。部署的目标是使代码能够在实际环境中运行,为用户提供服务。在部署阶段,需要注意配置管理、环境一致性等问题,确保部署的顺利进行。同时,还可以进行一些额外的验证和监控,以确保部署后的系统稳定运行。
三、C++项目中使用 GTest 的步骤
-
GTest 安装
- 从GitHub下载GTest的发布版本。
- 在Linux下,可以使用包管理工具(如apt-get)安装,或者从源代码编译安装。
- 在Windows下,可以通过MSYS2、vcpkg等工具进行安装。
- 在macOS下,可以使用Homebrew进行安装。
-
编写测试用例
-
函数测试用例示例:
TEST(FooTest, HandlesZeroInput) {EXPECT_EQ(Foo(0), 0); }
这个测试用例验证了
Foo
函数在输入为0时的行为。 -
类测试用例示例:
class ConfigureTest : public ::testing::Test { protected:void SetUp() override {config_ = new Configure();}void TearDown() override {delete config_;}Configure* config_; };TEST_F(ConfigureTest, DefaultSettings) {EXPECT_EQ(config_->GetSetting("default"), "value"); }
这个测试类验证了
Configure
类的默认设置。
-
-
运行测试用例
使用gtest
命令运行所有测试用例,例如:./your_test_executable
不同的断言宏如
EXPECT_EQ
、ASSERT_TRUE
等用于检查测试结果,确保代码行为符合预期。 -
运行测试用例
以下是一个完整的run_tests.sh
脚本示例,用于在GitLab CI/CD中运行GTest测试用例:
#!/bin/bash# 切换到构建目录
cd /path/to/your/build/directory# 运行测试可执行文件
./your_test_executable# 检查测试是否成功
if [ $? -ne 0 ]; thenecho "Tests failed!"exit 1
elseecho "All tests passed!"
fi
关键代码解释:
cd /path/to/your/build/directory
:切换到包含测试可执行文件的目录。./your_test_executable
:运行测试可执行文件。if [ $? -ne 0 ]; then ... fi
:检查上一个命令的退出状态,如果不为0(表示测试失败),则输出错误信息并退出脚本。
四、具体示例
以下提供更具体的示例,这些示例将展示如何在C++项目中使用Google Test(GTest)编写测试用例,并将其与GitLab CI/CD流水线结合使用。
1. GTest测试用例示例
假设我们有一个简单的C++类Calculator
,它有一个加法函数Add
。我们可以为这个函数编写一个GTest测试用例。
// Calculator.h
#ifndef CALCULATOR_H
#define CALCULATOR_Hclass Calculator {
public:int Add(int a, int b);
};#endif // CALCULATOR_H// Calculator.cpp
#include "Calculator.h"int Calculator::Add(int a, int b) {return a + b;
}// CalculatorTest.cpp
#include <gtest/gtest.h>
#include "Calculator.h"TEST(CalculatorTest, HandlesPositiveInput) {Calculator calc;EXPECT_EQ(calc.Add(1, 2), 3);EXPECT_EQ(calc.Add(10, 20), 30);
}TEST(CalculatorTest, HandlesZeroInput) {Calculator calc;EXPECT_EQ(calc.Add(0, 0), 0);EXPECT_EQ(calc.Add(5, 0), 5);
}TEST(CalculatorTest, HandlesNegativeInput) {Calculator calc;EXPECT_EQ(calc.Add(-1, -1), -2);EXPECT_EQ(calc.Add(-1, 1), 0);
}int main(int argc, char **argv) {::testing::InitGoogleTest(&argc, argv);return RUN_ALL_TESTS();
}
在这个示例中,我们定义了三个测试用例来验证Calculator
类的Add
函数。每个测试用例都使用EXPECT_EQ
宏来检查函数的输出是否与预期值相等。
2. GitLab CI/CD流水线配置示例
以下是一个简单的GitLab CI/CD .gitlab-ci.yml
配置文件示例,用于构建和运行上述GTest测试用例。
stages:- build- testbuild_job:stage: buildscript:- mkdir build- cd build- cmake ..- makeartifacts:paths:- build/CalculatorTest # 假设测试可执行文件生成在这个路径下test_job:stage: testscript:- cd build- ./CalculatorTest # 运行测试可执行文件dependencies:- build_job # 依赖构建阶段的jobonly:- main # 只在main分支上运行
在这个配置文件中,我们定义了两个阶段:build
和test
。build_job
负责编译项目,生成测试可执行文件,并将其作为构建产物保存。test_job
依赖build_job
,负责运行测试可执行文件,并验证测试结果。
3. run_tests.sh脚本示例
虽然GitLab CI/CD流水线可以直接在script
部分运行测试可执行文件,但有时我们可能希望使用一个单独的脚本来运行测试。以下是一个简单的run_tests.sh
脚本示例。
#!/bin/bash# 切换到构建目录
cd /path/to/your/project/build# 运行测试可执行文件
./CalculatorTest# 检查测试是否成功
if [ $? -ne 0 ]; thenecho "Tests failed!"exit 1
elseecho "All tests passed!"exit 0
fi
在这个脚本中,我们切换到构建目录,运行测试可执行文件,并根据其退出状态检查测试是否成功。如果测试失败,脚本将输出错误信息并退出;如果测试成功,则输出成功信息并正常退出。
如果希望在GitLab CI/CD流水线中添加一个测试步骤,需要创建一个新的作业(job),该作业专门用于运行测试脚本(run_tests.sh)。这个作业应该位于构建(build)和部署(deploy)作业之间,以确保在尝试部署之前,软件已经通过了必要的测试。
以下是如何在您的YAML文件中添加测试脚本的一个示例:
stages:- build- test # 新增的测试阶段- deploy# ...(其他配置保持不变)# 测试作业
test_job:stage: testdependencies:- build_job # 依赖于构建作业,确保测试运行的是最新的构建script:- # 运行测试名为'run_tests.sh'的脚本。- ./run_tests.sh# 如果测试失败,您可能希望流水线停止继续执行。# 使用'allow_failure: false'(默认行为)来确保测试失败时流水线失败。# 如果您想在测试失败时仍然继续流水线,可以使用'allow_failure: true'。allow_failure: false# 只有在特定的分支或标签上运行时,才包含此作业(可选)。only:- main # 或者您希望运行测试的任何其他分支# 使用特定的运行器标签(可选)。tags:- kubernetes-linux-runner-test # 或者任何适合运行测试的标签# ...(其他作业保持不变,如build_job和deploy_job)
请注意,上述示例中的路径和文件名可能需要根据您的实际项目结构进行调整。此外,您还需要确保您的 GitLab CI/CD Runner具有访问和构建项目的适当权限。
相关文章:

C++自动化测试:GTest 与 GitLab CI/CD 的完美融合
在现代软件开发中,自动化测试是保证代码质量和稳定性的关键手段。对于C项目而言,自动化测试尤为重要,它能有效捕捉代码中的潜在缺陷,提高代码的可维护性和可靠性。本文将重点介绍如何在C项目中结合使用Google Test(GTe…...
vscode连接远程开发机报错
远程开发机更新,vscode连接失败 报错信息 "install" terminal command done Install terminal quit with output: Host key verification failed. Received install output: Host key verification failed. Failed to parse remote port from server ou…...
神经网络12-Time-Series Transformer (TST)模型
Time-Series Transformer (TST) 是一种基于 Transformer 架构的深度学习模型,专门用于时序数据的建模和预测。TST 是 Transformer 模型的一个变种,针对传统时序模型(如 RNN、LSTM)在处理长时间依赖、复杂数据关系时的限制而提出的…...

IDEA 2024安装指南(含安装包以及使用说明 cannot collect jvm options 问题 四)
汉化 setting 中选择插件 完成 安装出现问题 1.可能是因为之前下载过的idea,找到连接中 文件,卸载即可。...

Fakelocation Server服务器/专业版 Centos7
前言:需要Centos7系统 Fakelocation开源文件系统需求 Centos7 | Fakelocation | 任务一 更新Centos7 (安装下载不再赘述) sudo yum makecache fastsudo yum update -ysudo yum install -y kernelsudo reboot//如果遇到错误提示为 Another app is curre…...

oracle的静态注册和动态注册
oracle的静态注册和动态注册 静态注册: 静态注册 : 指将实例的相关信息手动告知 listener 侦 听 器 , 可以使用netmgr,netca,oem 以及直接 vi listener.ora 文件来实现静态注册,在动态注册不稳定时使用,特点是:稳定&…...

机器翻译基础与模型 之四:模型训练
1、开放词表 1.1 大词表和未登陆词问题 理想情况下,机器翻译应该是一个开放词表(Open Vocabulary)的翻译任务。也就是,无论测试数据中包含什么样的词,机器翻译系统都应该能够正常翻译。 现实的情况是即使不断扩充词…...

Vue——响应式数据,v-on,v-bind,v-if,v-for(内含项目实战)
目录 响应式数据 ref reactive 事件绑定指令 v-on v-on 鼠标监听事件 v-on 键盘监听事件 v-on 简写形式 属性动态化指令 v-bind iuput标签动态属性绑定 img标签动态属性绑定 b标签动态属性绑定 v-bind 简写形式 条件渲染指令 v-if 遍历指令 v-for 遍历对象的值 遍历…...
ceph 18.2.4二次开发,docker镜像制作
编译环境要求 #需要ubuntu 22.04版本 参考https://docs.ceph.com/en/reef/start/os-recommendations/ #磁盘空间最好大于200GB #内存如果小于100GB 会有OOM的情况发生,需要重跑 目前遇到内存占用最高为92GB替换阿里云ubuntu 22.04源 将下面内容写入/etc/apt/sources.list 文件…...
产品经理的项目管理课
各位产品经理,大家下午好,今天我给大家分享的主题是“产品经理如何做好项目管理”。 其实,我是不想分享这个主题的,是因为在周会中大家投票对这个议题最感兴趣,11个同学中有7个投了这个主题,所以才有了这次…...
Linux 下的 AWK 命令详细指南与示例
目录 简介AWK 的主要特性基本语法示例1. 打印文件的所有行2. 打印特定字段3. 打印匹配模式的行4. 基于条件过滤并打印5. 使用内置变量6. 执行算术运算7. 字符串操作8. 使用 BEGIN 和 END 块9. 处理分隔符文件 高级功能自定义脚本使用外部变量 总结 简介 AWK 是 Linux 中功能强…...
FPGA经验谈系列文章——8、复位的设计
前言 剑法往往有着固定的招式套路,而写代码似乎也存在类似的情况。不知从何时起,众多 FPGA 工程师们在编写代码时开启了一种关于 always 语句块的流行写法,那就是: always @(posedge i_clk or negedge i_rstn) 就笔者所经历的诸多项目以及所接触到的不少工程师而言,大家在…...
C#里怎么样实现操作符重载?
C#里怎么样实现操作符重载? 一般情况,都是表示某种类型的类时,才会使用到操作符重载。 比如实现一个复数类。 在C#中,重载运算符是通过在类或结构中定义特殊的方法来实现的,这些方法的名称是operator关键字后跟要重载的运算符。例如,要重载+运算符,可以定义一个名为op…...

项目实战:Vue3开发一个购物车
这段HTML代码实现了一个简单的购物车实战小项目的前端页面,结合了Vue.js框架来实现数据响应式和交互逻辑。页面展示了购物车中的商品项,每个商品项有增减数量的按钮,并且能显示商品总数以及目前固定为0元的商品总价和总价计算。 【运用响应式…...

Oracle SQL*Plus中的SET VERIFY
在 Oracle SQL*Plus 中,SET VERIFY ON 和 SET VERIFY OFF 是两个用于控制命令执行前后显示变量值的命令。这些命令主要用于调试和验证 SQL 脚本中的变量替换情况。 一、参数说明 1.1 SET VERIFY ON 作用:启用变量替换的验证功能。当启用时,S…...

Spring AI 框架使用的核心概念
一、模型(Model) AI 模型是旨在处理和生成信息的算法,通常模仿人类的认知功能。通过从大型数据集中学习模式和见解,这些模型可以做出预测、文本、图像或其他输出,从而增强各个行业的各种应用。 AI 模型有很多种&…...

二叉树路径相关算法题|带权路径长度WPL|最长路径长度|直径长度|到叶节点路径|深度|到某节点的路径非递归(C)
带权路径长度WPL 二叉树的带权路径长度(WPL)是二叉树所有叶节点的带权路径长度之和,给定一棵二叉树T,采用二叉链表存储,节点结构为 其中叶节点的weight域保存该节点的非负权值,设root为指向T的根节点的指针,设计求W…...

前端:JavaScript (学习笔记)【2】
目录 一,数组的使用 1,数组的创建 [ ] 2,数组的元素和长度 3,数组的遍历方式 4,数组的常用方法 二,JavaScript中的对象 1,常用对象 (1)String和java中的Stri…...

[面试]-golang基础面试题总结
文章目录 panic 和 recover**注意事项**使用 pprof、trace 和 race 进行性能调试。**Go Module**:Go中new和make的区别 Channel什么是 Channel 的方向性?如何对 Channel 进行方向限制?Channel 的缓冲区大小对于 Channel 和 Goroutine 的通信有…...

【案例】泛微.齐业成助力北京中远大昌汽车实现数电票全流程管理
中远大昌统一发票共享平台上线三个多月以来,实现: 5000份 60000元 发票开具 成本节约 客户简介及需求分析 北京中远大昌汽车服务有限公司(以下简称“中远大昌”)成立于2002年,是中远海运集团所属香远(北…...
基于算法竞赛的c++编程(28)结构体的进阶应用
结构体的嵌套与复杂数据组织 在C中,结构体可以嵌套使用,形成更复杂的数据结构。例如,可以通过嵌套结构体描述多层级数据关系: struct Address {string city;string street;int zipCode; };struct Employee {string name;int id;…...

接口测试中缓存处理策略
在接口测试中,缓存处理策略是一个关键环节,直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性,避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明: 一、缓存处理的核…...

深入剖析AI大模型:大模型时代的 Prompt 工程全解析
今天聊的内容,我认为是AI开发里面非常重要的内容。它在AI开发里无处不在,当你对 AI 助手说 "用李白的风格写一首关于人工智能的诗",或者让翻译模型 "将这段合同翻译成商务日语" 时,输入的这句话就是 Prompt。…...
Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以?
Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以? 在 Golang 的面试中,map 类型的使用是一个常见的考点,其中对 key 类型的合法性 是一道常被提及的基础却很容易被忽视的问题。本文将带你深入理解 Golang 中…...

基于Flask实现的医疗保险欺诈识别监测模型
基于Flask实现的医疗保险欺诈识别监测模型 项目截图 项目简介 社会医疗保险是国家通过立法形式强制实施,由雇主和个人按一定比例缴纳保险费,建立社会医疗保险基金,支付雇员医疗费用的一种医疗保险制度, 它是促进社会文明和进步的…...

关于iview组件中使用 table , 绑定序号分页后序号从1开始的解决方案
问题描述:iview使用table 中type: "index",分页之后 ,索引还是从1开始,试过绑定后台返回数据的id, 这种方法可行,就是后台返回数据的每个页面id都不完全是按照从1开始的升序,因此百度了下,找到了…...
【AI学习】三、AI算法中的向量
在人工智能(AI)算法中,向量(Vector)是一种将现实世界中的数据(如图像、文本、音频等)转化为计算机可处理的数值型特征表示的工具。它是连接人类认知(如语义、视觉特征)与…...

vue3+vite项目中使用.env文件环境变量方法
vue3vite项目中使用.env文件环境变量方法 .env文件作用命名规则常用的配置项示例使用方法注意事项在vite.config.js文件中读取环境变量方法 .env文件作用 .env 文件用于定义环境变量,这些变量可以在项目中通过 import.meta.env 进行访问。Vite 会自动加载这些环境变…...
CMake控制VS2022项目文件分组
我们可以通过 CMake 控制源文件的组织结构,使它们在 VS 解决方案资源管理器中以“组”(Filter)的形式进行分类展示。 🎯 目标 通过 CMake 脚本将 .cpp、.h 等源文件分组显示在 Visual Studio 2022 的解决方案资源管理器中。 ✅ 支持的方法汇总(共4种) 方法描述是否推荐…...
Web 架构之 CDN 加速原理与落地实践
文章目录 一、思维导图二、正文内容(一)CDN 基础概念1. 定义2. 组成部分 (二)CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 (三)CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 …...