C++自动化测试:GTest 与 GitLab CI/CD 的完美融合

news2024/11/25 11:12:37

在现代软件开发中,自动化测试是保证代码质量和稳定性的关键手段。对于C++项目而言,自动化测试尤为重要,它能有效捕捉代码中的潜在缺陷,提高代码的可维护性和可靠性。本文将重点介绍如何在C++项目中结合使用Google Test(GTest)和GitLab CI/CD,特别是通过提供详细的脚本示例,展示如何实现高效的自动化测试流程。

一、GTest 简介

Google Test(GTest)是Google开发的一个C++测试框架,以其跨平台兼容性、丰富的断言宏、易于使用以及强大的功能而广受欢迎。GTest支持多种测试类型,包括单元测试、异常测试、死亡测试等,并且提供了灵活的测试套件和测试用例管理机制,使得编写和维护测试代码变得简单高效。

在这里插入图片描述

二、GitLab CI/CD 流水线概述

GitLab CI/CD流水线是一个强大的自动化部署和测试工具,它允许开发者在代码提交时自动执行一系列任务。流水线通常分为以下几个阶段:

  1. 构建(build)阶段
    在 GitLab CI/CD 流水线的构建阶段,主要任务是将 C++ 项目的代码进行编译和构建,生成可执行文件或库。这个阶段为后续的测试和部署阶段提供了基础。通过将源代码转化为可执行的形式,确保代码可以在不同的环境中运行。构建阶段的作用在于,它能够及时发现编译错误和依赖问题,避免在后续阶段浪费时间。如果构建阶段出现问题,可以快速定位并解决,提高开发效率。

  2. 测试(test)阶段
    在测试阶段,使用 GTest 具有重要意义。GTest(Google Test)是一个强大的 C++ 测试框架,它提供了丰富的断言和测试工具,可以对 C++ 项目进行高效的单元测试、集成测试等。在这个阶段,通过运行各种测试用例,可以确保代码的功能正常,及时发现潜在的问题。使用 GTest 可以提高测试的覆盖率和准确性,增强代码的可靠性。同时,结合 GitLab CI/CD,可以自动执行测试,提高测试的效率和一致性。在测试阶段,可以根据项目的需求,编写不同类型的测试用例,如功能测试、性能测试等,以全面验证代码的质量。

  3. 部署(deploy)阶段
    部署阶段的流程通常包括将构建好的代码部署到生产环境或其他目标环境中。首先,需要确保构建和测试阶段都成功完成,没有出现错误。然后,可以使用自动化工具或脚本来将代码部署到目标环境。部署的目标是使代码能够在实际环境中运行,为用户提供服务。在部署阶段,需要注意配置管理、环境一致性等问题,确保部署的顺利进行。同时,还可以进行一些额外的验证和监控,以确保部署后的系统稳定运行。

三、C++项目中使用 GTest 的步骤

  1. GTest 安装

    • 从GitHub下载GTest的发布版本。
    • 在Linux下,可以使用包管理工具(如apt-get)安装,或者从源代码编译安装。
    • 在Windows下,可以通过MSYS2、vcpkg等工具进行安装。
    • 在macOS下,可以使用Homebrew进行安装。
  2. 编写测试用例

    • 函数测试用例示例

      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类的默认设置。

  3. 运行测试用例
    使用gtest命令运行所有测试用例,例如:

    ./your_test_executable
    

    不同的断言宏如EXPECT_EQASSERT_TRUE等用于检查测试结果,确保代码行为符合预期。

  4. 运行测试用例
    以下是一个完整的run_tests.sh脚本示例,用于在GitLab CI/CD中运行GTest测试用例:

#!/bin/bash

# 切换到构建目录
cd /path/to/your/build/directory

# 运行测试可执行文件
./your_test_executable

# 检查测试是否成功
if [ $? -ne 0 ]; then
  echo "Tests failed!"
  exit 1
else
  echo "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_H

class 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
  - test

build_job:
  stage: build
  script:
    - mkdir build
    - cd build
    - cmake ..
    - make
  artifacts:
    paths:
      - build/CalculatorTest  # 假设测试可执行文件生成在这个路径下

test_job:
  stage: test
  script:
    - cd build
    - ./CalculatorTest  # 运行测试可执行文件
  dependencies:
    - build_job  # 依赖构建阶段的job
  only:
    - main  # 只在main分支上运行

在这个配置文件中,我们定义了两个阶段:buildtestbuild_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 ]; then
    echo "Tests failed!"
    exit 1
else
    echo "All tests passed!"
    exit 0
fi

在这个脚本中,我们切换到构建目录,运行测试可执行文件,并根据其退出状态检查测试是否成功。如果测试失败,脚本将输出错误信息并退出;如果测试成功,则输出成功信息并正常退出。

如果希望在GitLab CI/CD流水线中添加一个测试步骤,需要创建一个新的作业(job),该作业专门用于运行测试脚本(run_tests.sh)。这个作业应该位于构建(build)和部署(deploy)作业之间,以确保在尝试部署之前,软件已经通过了必要的测试。

以下是如何在您的YAML文件中添加测试脚本的一个示例:

stages:
  - build
  - test  # 新增的测试阶段
  - deploy

# ...(其他配置保持不变)

# 测试作业
test_job:
  stage: test
  dependencies:
    - 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具有访问和构建项目的适当权限。

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

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

相关文章

ubuntu16.04在ros使用USB摄像头-解决could not open /dev/video0问题

首先检查摄像头 lsusb 安装 uvc camera 功能包 sudo apt-get install ros-indigo-uvc-camera 安装 image 相关功能包 sudo apt-get install ros-kinetic-image-* sudo apt-get install ros-kinetic-rqt-image-view运行 uvc_camera 节点 首先输入roscore 然后另外开一个终端输入…

Linux:文件管理(二)——文件缓冲区

目录 一、缓冲区概念 二、缓冲区刷新机制 三、用缓冲区刷新解释下面现象。 一、缓冲区概念 缓冲区&#xff0c;本质就是一块内存区域。 设计缓冲区就是为了让本来要一次一次传的数据&#xff0c;都暂时传到缓冲区&#xff0c;让缓冲区刷新一次&#xff0c;这样只发生了一次传…

PH热榜 | 2024-11-24

DevNow 是一个精简的开源技术博客项目模版&#xff0c;支持 Vercel 一键部署&#xff0c;支持评论、搜索等功能&#xff0c;欢迎大家体验。 在线预览 1. AutoFlow Studio 标语&#xff1a;借助简化的AI质检&#xff0c;更快发布产品&#xff0c;更聪明地进行测试。 介绍&…

hubuctf-2024校赛-复现wp

web easyweb1 <?php error_reporting(0); highlight_file(__FILE__);$flag getenv("GZCTF_FLAG");if(isset($_GET[num])){$num $_GET[num];if(preg_match("/[0-9]/", $num)){die("You are failed.");}if(intval($num)){echo $flag;} } 利…

飞书会话消息左右排列

飞书会话消息左右排列 1. 飞书登录后&#xff0c;点击头像&#xff0c;弹出菜单有个按钮设置 2. 3.

《图像形态学运算全解析:原理、语法及示例展示》

简介&#xff1a; 本文详细介绍了图像形态学中的多种运算&#xff0c;包括腐蚀、膨胀、开运算、闭运算、形态学梯度运算、礼帽运算以及黑帽运算。分别阐述了各运算的原理、语法格式&#xff0c;并通过 Python 代码结合具体示例图片&#xff08;如erode.JPG、dilate.JPG、close.…

链路聚合实验

1、聚合方式 &#xff08;1&#xff09;、lacp 静态链路聚合、 动态链路聚合&#xff08;开启lacp模式&#xff0c;常用&#xff09; &#xff08;2&#xff09;、手工负载分担 静态端口聚合&#xff08;两台交换机都按照下面的命令配置&#xff09; <H3C>sys System Vi…

电子电气架构 -- ASIL D安全实现策略

我是穿拖鞋的汉子&#xff0c;魔都中坚持长期主义的汽车电子工程师。 老规矩&#xff0c;分享一段喜欢的文字&#xff0c;避免自己成为高知识低文化的工程师&#xff1a; 所有人的看法和评价都是暂时的&#xff0c;只有自己的经历是伴随一生的&#xff0c;几乎所有的担忧和畏惧…

禁止Chrome的自动升级

一、需求分析 因为用Chromeselenium做了网页自动化填写任务&#xff0c;如果Google Chrome浏览器自动升级&#xff0c;就会导致chromedriver加载失败&#xff0c;自动化任务失效&#xff0c;因此需要禁止Chrome浏览器的自动升级。 二、当前环境 三、实际配置 运行注册表编辑…

C0034.在Ubuntu中安装的Qt路径

Qt安装路径查询 在终端输入qmake -v如上中/usr/lib/x86_64-linux-gnu就是Qt的安装目录&#xff1b;

C++从零到满绩——类和对象(中)

目录 1>>前言 2>>构造函数&#xff08;我称之为初始化函数&#xff09; 3>>析构函数&#xff08;我称之为销毁函数&#xff09; 4>>拷贝构造函数&#xff08;我称之为复制函数&#xff09; 5>>运算符重载 5.2>>赋值运算符重载 ​编辑…

oracle 12c查看执行过的sql及当前正在执行的sql

V$SQL 提供了已经执行过及正在执行的SQL语句的信息。 一 查看共享池中所有sql的统计信息 #统计共享池中某类sql执行次数&#xff0c;总体执行时长&#xff0c;平均执行时长等信息&#xff0c;并按总体执行时长降序排序 SELECT INST_ID,SQL_ID,SQL_TEXT,SQL_FULLTEXT,EXECUTI…

解锁PPTist的全新体验:Windows系统环境下本地部署与远程访问

文章目录 前言1. 本地安装PPTist2. PPTist 使用介绍3. 安装Cpolar内网穿透4. 配置公网地址5. 配置固定公网地址 前言 在Windows系统环境中&#xff0c;如何本地部署开源在线演示文稿应用PPTist&#xff0c;并实现远程访问&#xff1f;本文将为您提供详细的部署和配置指南。 P…

C语言中的指针和字符串的赋值

前言&#xff1a;温习下以前学过的C语言知识&#xff0c;温故而知新。 实例说明 本文用一段实例代码阐述指针和字符串的联系。 #include <iostream> #include <cstring> int main() {using namespace std;char animal[20] "bear";const char * bird …

Linux高阶——1117—TCP客户端服务端

目录 1、sock.h socket常用函数 网络初始化函数 首次响应函数 测试IO处理函数 获取时间函数 总代码 2、sock.c SOCKET() ACCEPT()——服务端使用这个函数等待客户端连接 CONNECT()——客户端使用这个函数连接服务端 BIND()——一般只有服务端使用 LISTEN()——服务端…

物体网格弹性变形---Unity中实现

在游戏引擎场景中的3D物体是由一定数量的点、面组成的&#xff0c;如下图&#xff1a; 要使这些物体变形就是改变3D物体每个顶点状态。 1.首先在Unity场景中增加一个球体&#xff0c;如下图 3D组件默认拥有MeshFilter、meshRenderer、Collider组件&#xff0c;分别用来获取Mes…

【ArcGISPro】根据yaml构建原始Pro的conda环境

使用场景 我们不小心把原始arcgispro-py3的conda环境破坏了,我们就可以使用以下方法进行修复 查找文件 在arcgis目录下找到yaml文件 如果没找到请复制以下内容到新的yaml文件 channels: - esri - defaults dependencies: - anyio=4.2.0=py311haa95532_0 - appdirs=1.4.4=p…

【Y20030007】基于java+servlet+mysql的垃圾分类网站的设计与实现(附源码 配置 文档)

网垃圾分类网站的设计与实现 1.摘要2.开发目的和意义3.系统功能设计4.系统界面截图5.源码获取 1.摘要 随着全球环境保护意识的提升&#xff0c;垃圾分类已成为一项紧迫且重要的任务。为了有效推动垃圾分类的实施&#xff0c;提升公众的环保意识和参与度&#xff0c;垃圾分类已…

【Python爬虫五十个小案例】爬取豆瓣电影Top250

博客主页&#xff1a;小馒头学python 本文专栏: Python爬虫五十个小案例 专栏简介&#xff1a;分享五十个Python爬虫小案例 &#x1fab2;前言 在这篇博客中&#xff0c;我们将学习如何使用Python爬取豆瓣电影Top250的数据。我们将使用requests库来发送HTTP请求&#xff0c;…

C++ 优先算法 —— 长度最小的子数组(滑动窗口)

目录 题目&#xff1a;长度最小的子数组 1. 题目解析 2. 算法原理 Ⅰ. 暴力枚举 Ⅱ. 滑动窗口&#xff08;同向双指针&#xff09; 滑动窗口正确性 3. 代码实现 Ⅰ. 暴力枚举(会超时&#xff09; Ⅱ. 滑动窗口&#xff08;同向双指针&#xff09; 题目&#xff1a;长…