测试驱动开发:基于Jenkins+GoTest+HTML的持续化集成

目录

前言        

一、项目框架

1.项目迭代

2.项目时序图

3.项目测试执行

二、项目具体实现

1.创建流水线

2.拉取代码

3.执行测试代码

4.生成测试报告

5.报告内容解读

6.数据统计

7.邮件通知

8.企业微信通知

三、项目遇到的问题

1.go test -args 

2.go test生成html格式的报告

3.数据统计问题

4.相对路径问题

5.错误排查问题


前言        

       目前我们的项目体系流程不够完善,我们针对这一现象引入了“测试驱动开发”观念,在开发测试部署阶段可以节省一部分工作量,对于比较复杂的场景,也可以编写一些测试工具。我们都知道如果仅靠传统的手工测试(偏功能)会存在很多的漏洞,为了提高迭代效率,引入自动化测试、CI/CD,在项目测试阶段、预上线、上线等各个阶段都能快速通过上述手段发现问题,保障产品质量。

     


一、项目框架

        在日常测试过程中,需要验证测试环境&线上环境API接口,为了更方便,研究了通过Jenkins构建自动化项目并生成HTML报告。接下来会详细介绍项目构建步骤和遇到的问题。

1.项目迭代

2.项目时序图

3.项目测试执行


二、项目具体实现

1.创建流水线

(1)新建任务

(2)选择流水线或者复制现有流水线任务

(3)配置流水线

(4)pipeline脚本的基本框架

#!groovypipeline {agent anyenvironment {GO_BINARY = "go"TEST_REPORT_PATH = "test-report.xml"}stages {stage('checkout') {steps {sh"""echo "steps one""""}}stage('unit-test') {steps {echo "step two"}}stage('api-test') {steps {sh """ehco "step three""""}}}post {always {echo "clean over..."echo "send email"}success {echo 'Build && Test Succeeded.'}failure {echo 'Build && Test Failured.'}}}

对应在jenkins上的阶段视图:

2.拉取代码

repoURL = "git拉取代码地址"rootPath = "/var/jenkins_work/workspace/pid-openapi-test-report"repoPath = "${rootPath}/$BUILD_ID"...stages {stage('checkout') {steps {sh"""export PATH="${arcPath}:${goRoot}:${kubectlRoot}:${makeRoot}:$PATH"git clone --depth 1 ${repoURL} ${repoPath}"""}}...}

3.执行测试代码

利用go test命令执行代码。执行go test会进行全代码编译的,会拉取所有的依赖,所以需要提前配置go环境变量。

go test运行指定模块、指定优先级的测试用例,eg:

go test -v ./test/storage/... '-run=^Test+/TestP0' -json

./test/storage/ storage在openapi-go项目中的代码目录

'-run=^Test+/TestP0' ^Test指定Test打头的suite,/TestP0指定该suite下的用例。这样可以将模块storage、用例名称TestP0参数化为MODULE_NAME、PRIORITY,并在jenkins上的参数化构建中进行赋值。

配置完成后go test可以写成这样了:

go test -v ./test/$MODULE_NAME/...   -run="^Test"+"/Test"+$PRIORITY

4.生成测试报告

安装go-test-report

go get github.com/vakenbolt/go-test-report/

执行生成html格式测试报告的命令,会在当前目录生成一个test_report.html

go test -v ./test/$MODULE_NAME/...   -run="^Test"+"/Test"+$PRIORITY   -json | go-test-report

jenkins发布报告的pipeline script:

stage('Report') {           steps {echo "report"publishHTML (target: [allowMissing: false,alwaysLinkToLastBuild: false,keepAll: true,reportDir: '$BUILD_ID/test-output',reportFiles: 'test_report.html',reportName: "HTML Report"])}}

然后就可以在jenkins查看该报告了

5.报告内容解读

失败的用例是红色,通过的用例是绿色。失败日志需要关注assert部分的日志,包括报错行数、期望值与实际值的比较结果。

6.数据统计

在测试代码执行结果及报告都有了之后就可以统计自已需要的数据,然后放在邮件内容里进行发送。

先分析下html源文件的内容,找到自已想要的数据。

groovy自带解析html格式的库,但是不太好用。这里采用awk解析数据。

注:substr(s,p,n) 返回字符串s从p开始长度为n的部分

def genReportBody() {// 生成测试报告内容def testReport = readFile("$BUILD_ID/test-output/test_report.html")// 获取执行时间sh(script: 'pwd')def duration = sh(script: 'grep "Duration:" '+"$BUILD_ID/test-output/test_report.html"+' | awk \'{print substr($6,9,length($6)-17)}\'', returnStdout: true).trim()echo durationdef runtime = duration.split("\\.")[0].trim()echo runtime// 获取总数量def total = sh(script: 'grep "Total:" '+"$BUILD_ID/test-output/test_report.html"+' | awk \'{print substr($5,9,length($5)-26)}\'', returnStdout: true).trim()// 获取通过率def passedCount = sh(script: 'grep "Passed:" '+"$BUILD_ID/test-output/test_report.html"+' | awk \'{print substr($5,9,length($5)-17)}\'', returnStdout: true).trim()def skippedCount = sh(script: 'grep "Skipped:" '+"$BUILD_ID/test-output/test_report.html"+' | awk \'{print substr($5,9,length($5)-17)}\'', returnStdout: true).trim()def failedCount = sh(script: 'grep "Failed:" '+"$BUILD_ID/test-output/test_report.html"+' | awk \'{print substr($5,9,length($5)-17)}\'', returnStdout: true).trim()def passedRate = String.format("%.2f", passedCount.toInteger()/(total.toInteger()-skippedCount.toInteger()) * 100)

7.邮件通知

组装邮件中的内容

 // 生成测试报告def reportContent = """<h2>OpenAPI Test Report (${MODULE_NAME})</h2><p>Environment: ${ENV}</p><p>Test Time: ${runtime}s</p><h3>Test Cases:</h3><ul><a href="https://jenkins地址/view/pid/job/${JOB_NAME}/$BUILD_ID/HTML_20Report/" target="_blank">https://jenkins地址/view/pid/job/${JOB_NAME}/$BUILD_ID/HTML_20Report/</a></ul><p>Pass Rate: ${passedRate}% </p><p>Test Range: ${PRIORITY}</p><h3>Failures: ${failedCount}</h3>"""发送邮件,在发送邮件前将无用的测试数据清除post {always {sh """mv ${repoPath}/test-output ~/temprm -rf ${repoPath}/*mv ~/temp/test-output ${repoPath}/"""echo "clean over..."emailext body:  genReportBody(),subject: 'Test Report',// to: 'env.RECIPIENTS',to: '${RECIPIENT_LIST}',mimeType: 'text/html'// from: '邮件发送地址'}success {echo 'Build && Test Succeeded.'}failure {echo 'Build && Test Failured.'}}

8.企业微信通知


三、项目遇到的问题

1.go test -args 

利用该命令自定义参数时发现-args后面所有东西都当成agrs的值,且阻断后面所有指令的执行。后来在stackoverflow看见一个人发了同样的问题,我想到去看下官方说明

In addition to the build flags, the flags handled by 'go test' itself are:-argsPass the remainder of the command line (everything after -args)to the test binary, uninterpreted and unchanged.Because this flag consumes the remainder of the command line,the package list (if present) must appear before this flag.

上面的everything after -args和执行实际效果是一样。这样通过命令行方式来切换环境的做法是行不通,于是采用多个配置文件的方式,全部存放在jenkins机器的~/conf目录。

切换方式

if [ $ENV = "test" ]thenecho 'cp test .env'cp /home/jenkins/conf/.env ${repoPath}/testcp /home/jenkins/conf/.env.storage ${repoPath}/test/storage/v1/.envelif [ $ENV = "dev" ]then#statementsecho 'cp dev .env'cp /home/jenkins/conf/.env.dev ${repoPath}/test/.envcp /home/jenkins/conf/.env.storage.dev ${repoPath}/test/storage/v1/.envelif [ $ENV = "prod" ]thenecho 'cp prod .env'cp /home/jenkins/conf/.env.prod ${repoPath}/test/.envcp /home/jenkins/conf/.env.storage.prod ${repoPath}/test/storage/v1/.envfi

2.go test生成html格式的报告

最开始也是打算接入allure报告,但是发现go test并不支持,所以采用了go-test-report。发布的第一版的go test report时并不是长这样的

而是像下面这样不带css样式的

解决方法:在jenkins-->系统管理-->脚本命令行,输入以下命令

System.setProperty("hudson.model.DirectoryBrowserSupport.CSP", "")

3.数据统计问题

网上有很多groovy统计xml格式的文件,没找到能很好解析html格式的工具,想到awk这个工具。

def passedCount = sh(script: 'grep "Passed:" '+"$BUILD_ID/test-output/test_report.html"+' | awk \'{print substr($5,9,length($5)-17)}\'', returnStdout: true).trim()

4.相对路径问题

我们用IDE编写用例时直接就可以执行了,这种情况下go会把该用例所在的目录当成pwd目录;而流水线中go test是在项目根目录下执行的,这时go是把项目根目录当成pwd目录的。这样用例中使相对路径eg:.env、../.env等都会执行失败。

解决方法:利用runtime获取当前执行路径,然后代码中生成项目根目录,以该路径为基点再去拼接文件的路径,尽量不要使相对路径。

5.错误排查问题

后面发现现有的脚本case编写如果有一个报错,全部都是红色,找到报错点不是很方便,修改脚本case为:

func (s *JobBatchGetSuite) TestP0_Normal() {s.Run("TestSuccessJobBatchGet", func() {s.TestSuccessJobBatchGet()})
}func (s *JobBatchGetSuite) TestP1_Normal() {s.Run("TestJobBatchGetJobIdsTooMuch", func() {s.TestJobBatchGetJobIdsTooMuch()})
}

在jenkins上执行后,报告展示更为直观。

今天的分享就到此结束喽~

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

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

相关文章

【Qt】Qt配置

需要云服务器等云产品来学习Linux的同学可以移步/-->腾讯云<--/-->阿里云<--/-->华为云<--/官网&#xff0c;轻量型云服务器低至112元/年&#xff0c;新用户首次下单享超低折扣。 目录 一、Qt SDK下载 二、配置环境变量 三、新建工程(QWidget) 四、QWidg…

Kafka-消费者-KafkaConsumer分析-SubscriptionState

KafkaConsumer从Kafka拉取消息时发送的请求是FetchRequest(具体格式后面介绍),在其中需要指定消费者希望拉取的起始消息的offset。 为了消费者快速获取这个值&#xff0c;KafkaConsumer使用SubscriptionState来追踪TopicPartition与offset对应关系。 图展示了SubscriptionSta…

物联网与智慧城市的无界未来:如何打破传统束缚,开启智能生活新篇章

目录 一、物联网&#xff1a;连接万物的技术革命 1、物联网的发展历程 2、物联网的核心技术 二、智慧城市&#xff1a;未来城市的蓝图与挑战 1、智慧城市的蓝图 2、智慧城市建设面临的挑战 3、应对挑战的措施 三、物联网与智慧城市的融合&#xff1a;打破传统束缚&…

Android Matrix绘制PaintDrawable设置BitmapShader,手指触点为圆心scale放大原图,Kotlin

Android Matrix绘制PaintDrawable设置BitmapShader&#xff0c;手指触点为圆心scale放大原图&#xff0c;Kotlin 在 Android基于Matrix绘制PaintDrawable设置BitmapShader&#xff0c;以手指触点为中心显示原图的圆切图&#xff0c;Kotlin&#xff08;4&#xff09;-CSDN博客 的…

使用 Neo4j 和 LangChain 集成非结构化知识图增强 QA

目前基于大模型的信息检索有两种方法&#xff0c;一种是基于微调的方法&#xff0c;一种是基于 RAG 的方法。 信息检索和知识提取是一个不断发展的领域&#xff0c;随着大型语言模型&#xff08;LLM&#xff09;和知识图的出现&#xff0c;这一领域发生了显着的变化&#xff0…

全球移动通信市场,正在经历哪些新变化?

2023年已经结束了。回顾这一年的全球移动通信市场&#xff0c;如果让我用一个词来总结&#xff0c;那就是——“厚积薄发”。 从表面上来看&#xff0c;似乎并没有什么大事情发生。但实际上&#xff0c;平静的湖面之下&#xff0c;却是一片波涛汹涌、风云激荡。 无论是消费互联…

Zookeeper启动报错常见问题以及常用zk命令

Zk常规启动的命令如下 sh bin/zkServer.sh start 启动过程如果存在失败&#xff0c;是没办法直接看出什么问题&#xff0c;只会报出来 Starting zookeeper … FAILED TO START 可以用如下命令启动&#xff0c;便于查看zk启动过程中的详细错误 sh bin/zkServer.sh start-for…

ros2 基础学习16 - RQT:模块化可视化工具

RQT&#xff1a;模块化可视化工具 ROS中的Rviz功能已经很强大了&#xff0c;不过有些场景下&#xff0c;我们可能更需要一些简单的模块化的可视化工具&#xff0c;比如只显示一个摄像头的图像&#xff0c;使用Rviz的话&#xff0c;难免会觉得操作有点麻烦。 此时&#xff0c;我…

nexus3 npm-hosted仓库迁移

迁移背景&#xff1a; 从nexus 3.33 升级到 nexus 3.64 过程中&#xff0c;私服 npm-hosted 无法上传。由于这个 npm-hosted 和 npm-proxy 放的同一个 blob存储&#xff0c;无法单独拆除去&#xff0c;所以采用迁移的方式 迁移思路&#xff1a; down下来 npm-hosted 仓库&am…

pytest学习和使用-pytest如何进行分布式测试?(pytest-xdist)

1 什么是分布式测试&#xff1f; 在进行本文之前&#xff0c;先了解些基础知识&#xff0c;什么是分布式测试&#xff1f;分布式测试&#xff1a;是指通过局域网和Internet&#xff0c;把分布于不同地点、独立完成特定功能的测试计算机连接起来&#xff0c;以达到测试资源共享…

C——语言内存函数

目录 一、memcpy的使用和模拟实现 1.memcpy函数原型 2.memcpy函数的使用 3.memcpy函数的模拟实现 二、memmove的使用和模拟实现 1.memmove函数原型 2.memmove函数的使用 3.memmove函数的模拟实现 三、memset的使用 1.memset函数原型 2.memset函数的使用 四、memcmp…

蓝桥杯备赛 day 3 —— 高精度(C/C++,零基础,配图)

目录 &#x1f308;前言&#xff1a; &#x1f4c1; 高精度的概念 &#x1f4c1; 高精度加法和其模板 &#x1f4c1; 高精度减法和其模板 &#x1f4c1; 高精度乘法和其模板 &#x1f4c1; 高精度除法和其模板 &#x1f4c1; 总结 &#x1f308;前言&#xff1a; 这篇文…

设计一个网页爬虫

定义 User Case 和 约束 注意&#xff1a;没有一个面试官会阐述清楚问题&#xff0c;我们需要定义Use case和约束 Use cases 我们的作用域只是处理以下Use Case&#xff1a; Service 爬取一批 url 生成包含搜索词的单词到页面的反向索引给页面生成标题和片段– 标题和片段是…

迅为RK3588开发板编译 Buildroot单独编译图形化界面(打包镜像)

上面 Kernel/U-Boot/Recovery/Rootfs 各个部分的编译后&#xff0c;将打包要用到的所有固件移动到 rockdev 目录下&#xff0c;然后打包为完整的 update.img 镜像。 首先在 linux 源码目录下输入以下命令进入编译的 UI 界面&#xff0c;进入之后如下所示&#xff1a; ./buil…

gin+gorm增删改查目录框架

从网上找资料,发现,很多都是直接的结构 路由&#xff0c;后端的controller层&#xff0c;还有model层&#xff0c;都是放在了同一个main.go文件中&#xff0c;如果写项目的话&#xff0c;还得自己去拆文件&#xff0c;拆代码&#xff0c;经过查询和自己总结&#xff0c;下面放…

鸿蒙开发(四)UIAbility和Page交互

通过上一篇的学习&#xff0c;相信大家对UIAbility已经有了初步的认知。在上篇中&#xff0c;我们最后实现了一个小demo&#xff0c;从一个UIAbility调起了另外一个UIAbility。当时我提到过&#xff0c;暂不实现比如点击EntryAbility中的控件去触发跳转&#xff0c;而是在Entry…

vue 指定区域可拖拽的限定拖拽区域的div(如仅弹窗标题可拖拽的弹窗)

<template><div class"container" ref"container"><div class"drag-box" v-drag><div class"win_head">弹窗标题</div><div class"win_content">弹窗内容</div></div><…

pycharm import torch

目录 1 安装 2 conda环境配置 3 测试 开始学习Pytorch! 1 安装 我的电脑 Windows 11 Python 3.11 Anaconda3-2023.09-0-Windows-x86_64.exe cuda_11.8.0_522.06_windows.exe pytorch &#xff08;管理员命令行安装&#xff09; pycharm-community-2023.3.2.exe 2 c…

白山云基于StarRocks数据库构建湖仓一体数仓的实践

背景 随着每天万亿级别的业务数据流向数据湖&#xff0c;数据湖的弊端也逐渐凸显出来&#xff0c;例如&#xff1a; 数据入湖时效性差&#xff1a;数据湖主要依赖于离线批量计算&#xff0c;通常不支持实时数据更新&#xff0c;因此无法保证数据的强一致性&#xff0c;造成数…

js的防抖与节流

目录 认识防抖与节流防抖节流 手写防抖函数绑定this与参数取消功能立即执行获取返回值最终版 手写节流函数 认识防抖与节流 在JavaScript中&#xff0c;大量操作都会触发事件&#xff0c;这些事件又会被添加到事件队列中进行排队处理 某些事件如果频繁触发的话会对浏览器的性能…