go实战案例:如何结合 Jenkin 完成持续化集成和自动化测试?

news2026/3/24 15:44:04
今天我们主要来介绍如何结合Jenkins完成持续化集成和自动化测试的案例。在微服务开发团队中一般会采用敏捷开发这类增长式的开发方式这能有效提高各个微服务的迭代效率。为了让完成的代码能够尽快得到反馈我们建议尽早将完成的代码提交到代码库中被集成部署每天一次甚至一天多次通过自动构建和自动化测试尽早检测出集成的错误从而确保错误被尽快发现和纠正。持续集成与Jenkins Pipeline在敏捷开发中持续集成ClContinuousIntegration是为了更快地发现和修复系统集成遇到的各类问题它建议开发人员一天最少提交一次或者多次代码到代码库中让自动化工具对提交的代码进行集成部署并使用自动化测试工具检验代码是否正常运行从而更快地发现代码中存在的问题并进行修复。一般来说业务系统经过微服务划分后每一个微服务都是由独立的小团队进行开发和维护在系统集成时考虑到微服务之间存在大量的互相调用这就要求我们不仅要验证微服务内模块的集成结果还需要验证微服务之间的集成结果。因此持续集成能够加快各个小团队之间的协作及早发现系统集成中遇到的问题进而提升整个项目的开发效率。Jenkins是常用的持续集成工具。它采用Java 开发提供Web界面简化操作并支持插件式扩展可以处理几乎任何类型的构建和持续集成。Jenkins 中提供多种方式进行构建工作其中 Pipeline 是最为常用的方式之一。Pipeline是一套运行在Jenkins上的工作框架。它能够将多个节点中的任务连接起来实现单个节点难以完成的复杂流程的编排和可视化工作。Pipeline以代码的形式实现它将一个流水线划分为多个Stage每个 Stage代表了一组操作比如构建、测试、部署等而 Stage 内部又由多个Step 组成每一个 Step 就是基本的操作命令比如打印日志echo等命令。在本文的后半部分我们将通过一个Pipeline完成user服务从GitHub中拉取代码到编译打包成镜像再到部署到Kubernetes 的流程。Go的单元测试在前面的CI简易流程图中我们可以看到服务在经过构建和部署之后会进行相应的测试来验证部署的代码是否合理。Go本身提供了一套轻量级的测试框架用于对Go程序进行单元测试和基准测试。g0test命令是一个按照一定的约定和组织来测试代码的程序它执行的文件都是以_test.go”作为后缀这部分文件不会包含在gobuild的代码构建中在测试文件中主要存在以下三种函数类型1.以Test作为函数名前缀的测试函数一般用作单元测试测试函数的逻辑行为是否正确2.以Benchmark作为函数名前缀的基准测试函数一般用来衡量函数的性能3.以Example作为函数名前缀的示例函数主要用于提供示例文档。接下来我们通过user_dao_test.go测试文件介绍如何编写Go的单元测试用例代码如下所示package dao import ( testing func TestUserDAoImpl_Save(t *testing.T) { userDAO : UserDAOImpl{} err : InitMysql(127.0.0.1, 3306, root, 123456, user) if err ! nil{ t.Error(err) t.FailNow() } user : UserEntity{ Username:aoho, Password:aoho, Email:aohomail.com, } err userDAo.Save(user) if err ! nil{ t.Error(err) t.FailNow() } t.Logf(new User ID is %d, user.ID) } func TestUserDAoImpl_SelectByEmail(t *testing.T) { userDAO : UserDAOImpl{} err : InitMysql(127.0.0.1, 3306, root, 123456, user) if err ! nil{ t.Error(err) t.FailNow() } user, err : userDAo.SelectByEmail(aohomail.com) if err ! nilf t.Error(err) t.FailNow() } t.Logf(result uesrname is %s, user.Username) }一般来说测试文件会以待测试文件名_test.go的方式命名比如user_dao_test.go说明是对user_dao.go文件的测试用例。类似的测试函数也是以“Test待测试函数的方式进行命名比如TestUserDAOlmpl_SelectByEmail 是对UserDAOlmpl 结构体的 SelectByEmail方法进行测试你也可以根据测试路径的不同添加额外的修饰语。测试文件需要导入testing 包测试函数中的*testing.T参数用于报告测试结果和附加的日志信息。我们可以通过go test命令运行测试用例在 user_dao_test.go所在目录下执行go test 命令即可执行user_dao_test.go内所有的测试函数并在命令行打印相应的执行结果。使用Pipeline构建部署服务在部署Pipeline 服务之前我们首先将 user服务依赖的 MySQL和 Redis 独立部署到Kubernetes上这里我们以Redis的yaml配置为例apiversion: apps/v1 kind: Deployment metadata: name: user-redis labels: name: user-redis spec: replicas: 1 strategy: type: RollingUpdate selector: matchLabels: name: user-redis template: metadata: labels: name: user-redis spec: containers: #定义Redis容器开放6379端口 - name: user-redis image: redis:5.0 ports: - containerPort: 6379 imagePullpolicy: IfNotPresentuser-redis.yaml 文件通过 Deployment Controller 管理 Pod当 Controller 中的 Pod 出现异常被重启时很可能导致 Pod 的IP 发生变化。如果此时 user服务通过固定IP 的方式访问 Redis很可能会访问失败。为了避免这种情况我们可以为 user-redis Pod 定义一个 Service配置文件描述如下:apiversion: v1 kind: Service metadata: name: user-redis-service spec: selector: name : user-redis ports: - protocol: TCP port: 6379 targetPort: 6379 name: user-redis-tcp在创建好 Pod 后再执行 kubectl create -f user-redis-service.yaml 命令即可为 user-redis Pod 生成一个Service。Service 定义了一组 Pod 的逻辑集合和一个用于访问它们的策略Kubernetes集群会为 Service 分配一个固定的Cluster IP用于集群内部的访问。我们可以通过以下命令查看Service的信息包括 Cluster IP 等信息:kubectl get services通过Cluster IP访问MySQL和Redis等服务我们就无须担心PodIP的变化。通过 Pipeline 部署服务到 Kubernetes 集群主要有以下步骤1.从 GitHub 中拉取代码;2.构建Docker 镜像3.上传 Docker 镜像到 Docker Hub;4.将应用部署Kubernetes;5.接口测试。在 Pipeline 中我们将上述步骤组织成相应的 Stage让Jenkins 为我们完成服务的持续集成和自动化测试接下来我们以user服务的部署作为例子。Pipeline 脚本是由Groovy语言实现支持Declarative声明式和 Scripted脚本式语法我们接下来的演示就基于脚本式语法进行介绍。第一步拉取代码。Stage 的声明如下stage(clone code from github) { echo first stage: clone code git url: https://github.com/longjoy/micro-go-course.git script { commit_id sh(returnstdout: true, script: git rev-parse --short HEAD).trim() } }我们通过giturl命令从 GitHub中获取user服务的代码并将本次提交记录的commit_id 提取出来作为变量使用。接下来是第二步使用user服务中的Dockfile定义构建相应的user 镜像。Stage声明如下stage(build image) { echo second stage: build docker image sh docker build -t aoho/user:${commit_id} sectionl1/user/ }为了方便在排查问题时可以根据对应的代码记录定位代码我们采用了GitHub的提交记录commit_id作为镜像的 tag。同时为了将 MySQL 和 Redis 的地址作为参数传入修改 user 服务的 Dockerfile 为如下:FROM golang:latest wORKDIR /root/micro-go-course/sectionl0/user CopY / /root/micro-go-course/sectionl0/user RUN go env -w GOPRoxYhttps://goproxy.cn,direct RUN go build -o user EXP0SE 10086 ENTRYPoINT ./user -mysql.addr $mysqlAddr -redis.addr $redisAddrmysqlAddr 和 redisAddr 将在 user.yaml 配置文件中以环境变量的方式指定 MySQL 和 Redis 的地址。第三步为了方便Kubernetes拉取服务的镜像我们将第二步构建好的Docker镜像推送到镜像仓库中。如下声明所示:stage(push image) { echo third stage: push docker image to registry sh docker login -u eoho -p xxxxxx sh docker push aoho/user:${commit_id} }Docker 中默认的镜像仓库为 Docker Hub上述声明中就将 user 镜像推送到 Docker Hub 中当然你也可以选择将镜像推送到私有仓库中。往DockerHub中推送镜像需要提交账号密码这需要我们预先注册申请一个 Docker Hub账户。然后在第四步中我们使用kubectl将user服务部署到Kubernetes 中。为了保证部署到正确版本的镜像我们需要将 commit_id 替换到 user.yaml 文件中以及将 mysqlAddr 和 redisAddr 作为环境变量输入user.yaml的配置如下:apiversion: apps/v1 kind: Deployment metadata: name: user-service labels: name: user-service spec: replicas: 1 strategy: type: RollingUpdate selector: matchLabels: name: user-service template: metadata: labels: name: user-service spec: containers: #定义User容器开放10086端口 - name: user image: aoho/user:COMMIT_ID_TAG ports: - containerPort: 10086 imagePullpolicy: IfNotPresent env: - name: mysqlAddr value: MYSQL_ADDR_TAG - name: redisAddr value: REDIS_ADDR_TAG在上述配置文件中我们使用DeploymentController 来管理Pod创建Pod的模板为第二步中构建的user 镜像。构建第四步的 Stage 声明如下:stage(deploy to Kubernetes) { echo forth stage: deploy to Kubernetes sh sed -i s/COMMIT_ID_TAG/${commit_id}/ user.yam] sh sed -i s/MYSQL_ADDR_TAG/${mysql_addr}/ user.yam] sh sed -i s/REDIS_ADDR_TAG/${redis_addr}/ user.yaml sh kubectl apply -f user.yaml }在上述声明中我们首先使用 sed 命令将yaml 文件中标识替换为对应的变量再通过 kubectl apply命令重新部署了user-servicePod。为了让user服务的接口在Kubernetes集群外也能够访问我们通过NodePort的方式将user服务的端口暴露到 Node 节点的相应端口定义 user-service.yaml 配置如下:apiversion: v1 kind: Service metadata: name: user-service-http spec: selector: name : user-service type: NodePort ports: - protocol: TCP port: 10086 targetPort: 10086 nodePort: 30036 name: user-service-tcp在上述配置中我们指定的Service的类型为NodePort并将user服务的接口通过Node 节点的30036暴露出去对此我们就可以在集群外部通过NodelP:NodePort的方式访问user服务了。最后一步我们通过gotest对user中的HTTP接口进行接口测试验证代码集成的效果。Stage声明如下:stage(http test) { echo fifth stage: http test sh cd sectionl1/user/transport go test -args ${user_addr} }上述 Stage 中 user_addr 变量即 NodelP:NodePortuser 服务通过 NodePort 暴露到 Kubernetes集群外的可访问端口。我们使用go test命令运行了transport包下的测试文件用于测试HTTP接口。到此我们通过Pipeline对user服务进行持续集成和测试的整个流程就已经完成了其完整的Pipeline脚本如下:node { script { mysql_addr 127.0.0.1 // service cluster ip redis_addr 127.0.0.1 // service cluster ip user_addr 127.0.0.1:30036 // nodeIp : port } stage(clone code from github) { echo first stage: clone code git url: https://github.com/longjoy/micro-go-course.git script { commit_id sh(returnstdout: true, script: git rev-parse --short HEAD).trim() } } stage(build image) { echo second stage: build docker image sh docker build -t aoho/user:${commit_id} sectionl1/user/ } stage(push image) { echo third stage: push docker image to registry sh docker login -u aoho -p xxxxxx sh docker push aoho/user:${commit_id} } stage(deploy to Kubernetes) { echo forth stage: deploy to Kubernetes sh sed -i s/COMMIT_ID_TAG/${commit_id}/ user-service.yaml sh sed -i s/MYSQL_ADDR_TAG/${mysql_addr}/ user-service.yaml sh sed -i s/REDIS_ADDR_TAG/${redis_addr}/ user-service.yaml sh kubectl apply -f user.yaml } stage(http test) { echo fifth stage: http test sh cd sectionl1/user/transport go test -args ${user_addr} } }我们可以在Jenkins 中创建一个 Pipeline任务将上述脚本复制到Script区域中保存后触发构建不过在这之前需要在Jenkins 中安装和配置好 Kubernetes Plugin 和 Docker Plugin。在实际的开发中我们可以将上述Pipeline脚本放入到Jenkinsfile中与代码一同提交到代码库将Pipeline任务的脚本配置类型修改为 Pipeline Script from SCM引I用代码库中 Pipeline 脚本进行构建。下图为在Pipeline 中构建user 服务的结果视图绿色表示该 Stage 执行成功。Pipeline中构建user服务的结果视图小结持续集成和自动化测试能够对开发代码进行快速校验和反馈帮助开发人员更早地发现代码中的集成Bug并进行修改有效提高团队的开发效率。在本文我们主要介绍了如何通过Jenkins对服务进行持续集成和自动化测试。我们借助了JenkinsPipeline的能力把user服务的代码从代码库拉取出来打包成user镜像并将镜像部署到Kubernetes集群最后还通过gotest对user服务中提供的HTTP接口进行测试其实除了手动触发构建外Jenkins中还支持多种触发器比如通过Webhook监听代码库中代码的变化在代码库发生提交或者合并时自动触发一次构建任务这能大大提升持续集成的效率。自动化测试也存在其他多种多样的方式比如借助JMeter和Jenkins对服务进行性能测试等。希望通过本文的学习能够帮助你了解持续集成和自动化测试的基本流程并掌握使用Jenkins进行持续集成的能力。

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

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

相关文章

SpringBoot-17-MyBatis动态SQL标签之常用标签

文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…

wordpress后台更新后 前端没变化的解决方法

使用siteground主机的wordpress网站,会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后,网站没有变化的情况。 不熟悉siteground主机的新手,遇到这个问题,就很抓狂,明明是哪都没操作错误&#x…

网络编程(Modbus进阶)

思维导图 Modbus RTU(先学一点理论) 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议,由 Modicon 公司(现施耐德电气)于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…

UE5 学习系列(二)用户操作界面及介绍

这篇博客是 UE5 学习系列博客的第二篇,在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下: 【Note】:如果你已经完成安装等操作,可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作,重…

IDEA运行Tomcat出现乱码问题解决汇总

最近正值期末周,有很多同学在写期末Java web作业时,运行tomcat出现乱码问题,经过多次解决与研究,我做了如下整理: 原因: IDEA本身编码与tomcat的编码与Windows编码不同导致,Windows 系统控制台…

利用最小二乘法找圆心和半径

#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …

使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式

一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明&#xff1a;假设每台服务器已…

XML Group端口详解

在XML数据映射过程中&#xff0c;经常需要对数据进行分组聚合操作。例如&#xff0c;当处理包含多个物料明细的XML文件时&#xff0c;可能需要将相同物料号的明细归为一组&#xff0c;或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码&#xff0c;增加了开…

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造&#xff0c;完美适配AGV和无人叉车。同时&#xff0c;集成以太网与语音合成技术&#xff0c;为各类高级系统&#xff08;如MES、调度系统、库位管理、立库等&#xff09;提供高效便捷的语音交互体验。 L…

(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)

题目&#xff1a;3442. 奇偶频次间的最大差值 I 思路 &#xff1a;哈希&#xff0c;时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况&#xff0c;哈希表这里用数组即可实现。 C版本&#xff1a; class Solution { public:int maxDifference(string s) {int a[26]…

【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型

摘要 拍照搜题系统采用“三层管道&#xff08;多模态 OCR → 语义检索 → 答案渲染&#xff09;、两级检索&#xff08;倒排 BM25 向量 HNSW&#xff09;并以大语言模型兜底”的整体框架&#xff1a; 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后&#xff0c;分别用…

【Axure高保真原型】引导弹窗

今天和大家中分享引导弹窗的原型模板&#xff0c;载入页面后&#xff0c;会显示引导弹窗&#xff0c;适用于引导用户使用页面&#xff0c;点击完成后&#xff0c;会显示下一个引导弹窗&#xff0c;直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…

接口测试中缓存处理策略

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

龙虎榜——20250610

上证指数放量收阴线&#xff0c;个股多数下跌&#xff0c;盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型&#xff0c;指数短线有调整的需求&#xff0c;大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的&#xff1a;御银股份、雄帝科技 驱动…

观成科技:隐蔽隧道工具Ligolo-ng加密流量分析

1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具&#xff0c;该工具基于TUN接口实现其功能&#xff0c;利用反向TCP/TLS连接建立一条隐蔽的通信信道&#xff0c;支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式&#xff0c;适应复杂网…

铭豹扩展坞 USB转网口 突然无法识别解决方法

当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…

未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?

编辑&#xff1a;陈萍萍的公主一点人工一点智能 未来机器人的大脑&#xff1a;如何用神经网络模拟器实现更智能的决策&#xff1f;RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战&#xff0c;在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…

Linux应用开发之网络套接字编程(实例篇)

服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …

华为云AI开发平台ModelArts

华为云ModelArts&#xff1a;重塑AI开发流程的“智能引擎”与“创新加速器”&#xff01; 在人工智能浪潮席卷全球的2025年&#xff0c;企业拥抱AI的意愿空前高涨&#xff0c;但技术门槛高、流程复杂、资源投入巨大的现实&#xff0c;却让许多创新构想止步于实验室。数据科学家…

深度学习在微纳光子学中的应用

深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向&#xff1a; 逆向设计 通过神经网络快速预测微纳结构的光学响应&#xff0c;替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…