前言
老铁们,咱们用 JMeter 跑测试的时候,最直观的就是盯着"查看结果树"看结果对吧?等到接口一个个都调通了,后面就得面对一个现实------敏捷开发嘛,迭代是逃不掉的。每次迭代都得把接口测试再跑一遍,这重复的活儿干多了,脑子都快变复读机了......那咋整?当然得搞持续集成啦!那么问题来了:咱们具体该怎么把这事儿集成起来呢?------这就来聊聊本期的话题。
咱们依旧截图+步骤详细整合,看完一定有帮助
text
✔️ 每天到点自动执行 JMeter 脚本
✔️ 生成带请求/响应详情的 Allure 报告
✔️ Jenkins 集成 HTML 报告且样式不丢失
✔️ 一套 build.xml 通用模板,改路径直接用
目录
- 前言
- 一、精通Jmeter接口测试命令模式运行
-
- [1. 命令行的参数](#1. 命令行的参数)
-
- [`-n` 和 `-t` 必须一起使用,不能单独使用](#
-n和-t必须一起使用,不能单独使用) - [`-l` 表示用来生成 jtl 报告](#
-l表示用来生成 jtl 报告) - [`-e` 和 `-o` 必须一起使用,不能单独使用](#
-e和-o必须一起使用,不能单独使用)
- [`-n` 和 `-t` 必须一起使用,不能单独使用](#
- [2. 使用示例及报错处理](#2. 使用示例及报错处理)
- 二、精通Jmeter接口测试集成Ant运行
- 三、精通Jmeter接口测试集成Ant生成Allure报告
- 四、精通Jmeter接口测试Jenkins持续集成
-
- 1、安装Jenkins,建议去官网安装最新版本
-
- [1.1 下载](#1.1 下载)
- [1.2 启动服务并访问](#1.2 启动服务并访问)
- [1.3 初始化安装插件](#1.3 初始化安装插件)
- [1.4 修改密码👤](#1.4 修改密码👤)
- [1.5 修改插件的下载位置(可选)](#1.5 修改插件的下载位置(可选))
-
- 1). 停止当前运行的 Jenkins. 停止当前运行的 Jenkins)
- 2). 迁移原有数据(可选). 迁移原有数据(可选))
- 3). 启动时指定新的家目录. 启动时指定新的家目录)
- [1.6 下载HTML报告的插件和Allure报告的插件](#1.6 下载HTML报告的插件和Allure报告的插件)
- 2、插件配置
-
- Allure插件配置
-
- 1) 点击设置 点击设置)
- 2)点击全局工具配置
- 3、Jenkins的配置
-
- [3.1 点击【+新建Item】](#3.1 点击【+新建Item】)
- [3.2 起一个名字](#3.2 起一个名字)
- [3.3 选择任务类型:自由风格的(Freestyle project)](#3.3 选择任务类型:自由风格的(Freestyle project))
- [3.4 做项目(任务)配置:点击高级,勾选自定义工作空间](#3.4 做项目(任务)配置:点击高级,勾选自定义工作空间)
- [3.5 指定Jmeter测试脚本所在的目录](#3.5 指定Jmeter测试脚本所在的目录)
- [3.6 点击【增加构建步骤】:选择执行windows的批处理命令并输入执行的命令](#3.6 点击【增加构建步骤】:选择执行windows的批处理命令并输入执行的命令)
- [3.7 点击保存之后呢,我们会跳到如下界面【开始执行】](#3.7 点击保存之后呢,我们会跳到如下界面【开始执行】)
- [3.8 其他介绍](#3.8 其他介绍)
- [3.9 Jenkins去集成我们的Allure报告](#3.9 Jenkins去集成我们的Allure报告)
-
- 1)我们要生成对应的报告
- 2)点击配置
- [3)找到构建之后操作步骤->allure report](#3)找到构建之后操作步骤->allure report)
- 4)勾选之后会有如下页面
- 5)配置JSON报告所在的地址,细节看图
- 6)往下翻,找到高级展开,配置html报告的地址
- 7)点击保存,再执行一次
- 8)我们的报告集成成功
- [3.10 Jenkins去集成我们的HTML报告](#3.10 Jenkins去集成我们的HTML报告)
- [3.11 定时自定执行脚本](#3.11 定时自定执行脚本)
- 五、写在最后
一、精通Jmeter接口测试命令模式运行
1. 命令行的参数
-n 和 -t 必须一起使用,不能单独使用
-n:表示命令行模式(非GUI)-t:指定你的 JMeter 的.jmx脚本
-l 表示用来生成 jtl 报告
好比是一个中转站 ,通过 jtl 的报告可以衍生出其他格式,比如将 jtl 报告转换成 HTML 的报告
注意:
-l是可选的,如果你直接用-e -o生成 HTML 报告,可以不带-l。
-e 和 -o 必须一起使用,不能单独使用
-e:表示生成 HTML 格式的报告-o:指定报告的输出目录
但是对于这个输出目录这个目录必须是一个空目录,如果里面有内容,那么它就会报错。
另外:
-e -o通常要和-n -t(运行测试)或者-g(已有 jtl 文件)配合使用。-e -o只支持csv格式,即jmeter.save.saveservice.output_format=csv(所以需要修改:bin/jmeter.propties文件,我们后面会讲怎么修改)
2. 使用示例及报错处理
1、首先你看,我们前面两篇博客所做的接口测试如下:👇

2、那么现在我先将Jmeter这个软件给关闭,然后呢,我们打开测试01.jmx这个脚本

3、然后:我们把它拷贝到如下所示的目录中去👇

4、此时我们打开我们的dos命令窗口,然后切换到我们刚才的E:\接口测试工具的使用\命令使用Jmeter目录里面去。

5、此时我们就开始使用命令jmeter -n -t 指定脚本.jmx -l jtl报告名.jtl

但是这种jtl报告我们是读不懂的,它好比就是一个中间的报告,我们得通过它转换成html报告,如下👇
jmeter -n -t 测试01.jmx -l result.jtl -e -o test

问题:如果你这里面的配置文件没有进行如下的设置,那么一定会报错的,就是说,




6、OK,最后我们来观察我们的html报告,如下👇

报告中的信息描述 如下👇:
1)
2)

3)

4)

上述我们是需要说比较麻烦的命令才得到我们的结果,那其实它有个比较简单的方法,就是我们可以集成Ant来为什么做上述的事情,如何集成呢?老铁,继续向后看~~
二、精通Jmeter接口测试集成Ant运行
你只需要一步一步的跟着我做如下步骤即可,👇
1、下载Ant压缩包并解压然后配置PATH变量
🚀JMeter 5.6.3 要求:Ant 版本 ≥ 1.10.1
1.1、下载Ant压缩包
1.2、解压缩


1.3、配置PATH变量
把ant的bin目录配置到PATH目录,如下👇


2、配置ant的编译文件build.xml
2.1、build.xml文件模版
xml
<?xml version="1.0" encoding="UTF-8"?>
<project name="ant-jmeter-test" default="run" basedir=".">
<property environment="env"/>
<tstamp>
<format property="time" pattern="yyyy_MM_dd_hh_mm" />
</tstamp>
<!-- 需要调用的jmeter目录,根据需要进行修改,本次使用的linux路径-->
<property name="jmeter.home" value="此处修改为你的JMeter安装目录" />
<property name="report.title" value="接口自动化测试"/>
<!-- jmeter生成jtl格式的结果报告的路径-->
<property name="jmeter.result.jtl.dir" value="此处修改为你的jtl报告存放目录" />
<!-- jmeter生成html格式的结果报告的路径-->
<property name="jmeter.result.html.dir" value="此处修改为你的html报告存放目录" />
<!-- 【详细报告】jmeter生成html格式的详细报告的路径-->
<property name="jmeter.result.html.dir1" value="report" />
<!-- 生成的报告的前缀-->
<property name="ReportName" value="接口自动化汇总报告" />
<property name="ReportName1" value="接口自动化详细报告" />
<property name="jmeter.result.jtlName" value="${jmeter.result.jtl.dir}/${ReportName}.jtl" />
<property name="jmeter.result.htmlName" value="${jmeter.result.html.dir}/${ReportName}.html" />
<!-- 【详细报告】详细报告的文件名-->
<property name="jmeter.result.htmlName1" value="${jmeter.result.html.dir1}/${ReportName1}.html" />
<target name="run">
<!--antcall target="delete" /-->
<antcall target="test" />
<antcall target="report" />
</target>
<!-- 该命令用来删除今天已经执行过的jtl,防止旧数据重叠
<target name ="delete">
<delete file="${jmeter.result.jtl.dir}/${ReportName}${env.BUILD_ID}.jtl"/>
</target>
-->
<!-- 该命令为执行命令-->
<target name="test">
<taskdef name="jmeter" classname="org.programmerplanet.ant.taskdefs.jmeter.JMeterTask" />
<jmeter jmeterhome="${jmeter.home}" resultlog="${jmeter.result.jtlName}">
<!-- 声明要运行的脚本路径"*.jmx"指包含此目录下的所有jmeter脚本-->
<testplans dir="此处修改为你的jmx脚本存放目录" includes="*.jmx" />
<property name="jmeter.save.saveservice.output_format" value="xml"/>
</jmeter>
</target>
<path id="xslt.classpath">
<fileset dir="${jmeter.home}/lib" includes="xalan*.jar"/>
<fileset dir="${jmeter.home}/lib" includes="serializer*.jar"/>
</path>
<!-- 该命令为生成汇总和详细报告 -->
<target name="report">
<tstamp> <format property="report.datestamp" pattern="yyyy/MM/dd HH:mm" /></tstamp>
<xslt
classpathref="xslt.classpath"
force="true"
in="${jmeter.result.jtlName}"
out="${jmeter.result.htmlName}"
style="${jmeter.home}/extras/jmeter-results-report_21.xsl">
<param name="dateReport" expression="${report.datestamp}"/>
</xslt>
<!-- 【详细报告】指定详细报告模板文件-->
<xslt
classpathref="xslt.classpath"
force="true"
in="${jmeter.result.jtlName}"
out="${jmeter.result.htmlName1}"
style="${jmeter.home}/extras/jmeter.results.shanhe.me.xsl">
<param name="dateReport" expression="${report.datestamp}"/>
</xslt>
<!-- 因为上面生成报告的时候,不会将相关的图片也一起拷贝至目标目录,所以,需要手动拷贝 -->
<copy todir="${jmeter.result.html.dir}">
<fileset dir="${jmeter.home}/extras">
<include name="collapse.png" />
<include name="expand.png" />
</fileset>
</copy>
<!-- 【详细报告】拷贝图片到目标目录-->
<copy todir="${jmeter.result.html.dir1}">
<fileset dir="${jmeter.home}/extras">
<include name="collapse.png" />
<include name="expand.png" />
</fileset>
</copy>
</target>
</project>
2.2、这个build需要改动的地方如下:
bash
jmeter的目录:<property name="jmeter.home" value="此处修改为JMeter安装目录" />
jtl报告的目录:<property name="jmeter.result.jtl.dir" value="此处修改为jtl报告存放目录" />
html报告的目录:<property name="jmeter.result.html.dir" value="此处修改为html报告存放目录" />
jmx脚本的目录:<testplans dir="此处修改为jmx脚本存放目录" includes="*.jmx" />
2.3、简述原因
jmeter的目录:<property name="jmeter.home" value="此处修改为JMeter安装目录" />
原因:指定本地JMeter的根安装路径,Ant才能调用JMeter执行脚本,必须填写你电脑上真实的JMeter安装目录
jtl报告的目录:<property name="jmeter.result.jtl.dir" value="此处修改为jtl报告存放目录" />
原因:设置JMeter执行后生成的jtl结果文件的保存路径,需自定义本地文件夹路径
html报告的目录:<property name="jmeter.result.html.dir" value="此处修改为html报告存放目录" />
原因:设置JMeter测试后生成的HTML汇总报告的保存路径,需自定义本地文件夹路径
jmx脚本的目录:<testplans dir="此处修改为jmx脚本存放目录" includes="*.jmx" />
原因:指定需要执行的JMeter测试脚本(.jmx文件)所在的目录,Ant会读取该目录下所有脚本执行,必须填写脚本真实路径
2.4、build.xml的配置
OK,那么我们开始配置build.xml文件了:
1)首先为了防止我们的后续出问题,我们将Jmeter脚本测试01.jmx放到非根目录和非中文目录中

2)然后我们的build.xml 必须放在 JMeter 脚本(.jmx)所在的目录
因此我们在测试01.jmx所在目录中建一个build.xml,如下

3)然后我们打开这个配置文件并将上述中的build.xml的模版拷贝进去

4)修改之后的配置文件如下:



代码
xml
<?xml version="1.0" encoding="UTF-8"?>
<project name="ant-jmeter-test" default="run" basedir=".">
<property environment="env"/>
<tstamp>
<format property="time" pattern="yyyy_MM_dd_hh_mm" />
</tstamp>
<!-- 需要调用的jmeter目录,根据需要进行修改,本次使用的linux路径-->
<property name="jmeter.home" value="D:\apache-jmeter-5.6.3" />
<property name="report.title" value="接口自动化测试"/>
<!-- jmeter生成jtl格式的结果报告的路径-->
<property name="jmeter.result.jtl.dir" value="E:\ants\jtl" />
<!-- jmeter生成html格式的结果报告的路径-->
<property name="jmeter.result.html.dir" value="E:\ants\html" />
<!-- 【详细报告】jmeter生成html格式的详细报告的路径-->
<property name="jmeter.result.html.dir1" value="report" />
<!-- 生成的报告的前缀-->
<property name="ReportName" value="接口自动化汇总报告" />
<property name="ReportName1" value="接口自动化详细报告" />
<property name="jmeter.result.jtlName" value="${jmeter.result.jtl.dir}/${ReportName}.jtl" />
<property name="jmeter.result.htmlName" value="${jmeter.result.html.dir}/${ReportName}.html" />
<!-- 【详细报告】详细报告的文件名-->
<property name="jmeter.result.htmlName1" value="${jmeter.result.html.dir1}/${ReportName1}.html" />
<target name="run">
<!--antcall target="delete" /-->
<antcall target="test" />
<antcall target="report" />
</target>
<!-- 该命令用来删除今天已经执行过的jtl,防止旧数据重叠
<target name ="delete">
<delete file="${jmeter.result.jtl.dir}/${ReportName}${env.BUILD_ID}.jtl"/>
</target>
-->
<!-- 该命令为执行命令-->
<target name="test">
<taskdef name="jmeter" classname="org.programmerplanet.ant.taskdefs.jmeter.JMeterTask" />
<jmeter jmeterhome="${jmeter.home}" resultlog="${jmeter.result.jtlName}">
<!-- 声明要运行的脚本路径"*.jmx"指包含此目录下的所有jmeter脚本-->
<testplans dir="E:\ants" includes="*.jmx" />
<property name="jmeter.save.saveservice.output_format" value="xml"/>
</jmeter>
</target>
<path id="xslt.classpath">
<fileset dir="${jmeter.home}/lib" includes="xalan*.jar"/>
<fileset dir="${jmeter.home}/lib" includes="serializer*.jar"/>
</path>
<!-- 该命令为生成汇总和详细报告 -->
<target name="report">
<tstamp> <format property="report.datestamp" pattern="yyyy/MM/dd HH:mm" /></tstamp>
<xslt
classpathref="xslt.classpath"
force="true"
in="${jmeter.result.jtlName}"
out="${jmeter.result.htmlName}"
style="${jmeter.home}/extras/jmeter-results-report_21.xsl">
<param name="dateReport" expression="${report.datestamp}"/>
</xslt>
<!-- 【详细报告】指定详细报告模板文件-->
<xslt
classpathref="xslt.classpath"
force="true"
in="${jmeter.result.jtlName}"
out="${jmeter.result.htmlName1}"
style="${jmeter.home}/extras/jmeter.results.shanhe.me.xsl">
<param name="dateReport" expression="${report.datestamp}"/>
</xslt>
<!-- 因为上面生成报告的时候,不会将相关的图片也一起拷贝至目标目录,所以,需要手动拷贝 -->
<copy todir="${jmeter.result.html.dir}">
<fileset dir="${jmeter.home}/extras">
<include name="collapse.png" />
<include name="expand.png" />
</fileset>
</copy>
<!-- 【详细报告】拷贝图片到目标目录-->
<copy todir="${jmeter.result.html.dir1}">
<fileset dir="${jmeter.home}/extras">
<include name="collapse.png" />
<include name="expand.png" />
</fileset>
</copy>
</target>
</project>
3、配置库文件
3.1、为什么需要配置库文件?
我们刚刚不是下载一个一个Ant吗?那么我们怎么让Ant和Jmeter关联呢?这个问题就是我们为何需要配置库文件的原因了。

3.2、如何配置让他们关联?做以下两步
1)把 jmeter.results.shanhe.me.xsl 文件,复制到 你的JMeter安装目录 → extras文件夹 里
2)把 你的JMeter安装目录 → extras文件夹 里的 ant-jmeter-1.1.1.jar 文件,复制到 你的Ant安装目录 → lib文件夹 里
注意:
jmeter.results.shanhe.me.xsl属于第三方美化版详细报告模板,JMeter原始安装包无此文件,需单独下载
3.3 开始实操
1)去下载jmeter.results.shanhe.me.xsl文件
下载地址:jmeter.results.shanhe.me.xsl文件
当然,如果不下载就直接使用如下源码
xml
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="html" indent="no" encoding="UTF-8" doctype-public="-//W3C//DTD HTML 4.01 Transitional//EN" doctype-system="http://www.w3.org/TR/html4/loose.dtd"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/testResults">
<html lang="en">
<head>
<meta name="Author" content="shanhe.me"/>
<title>JMeter Test Results</title>
<style type="text/css"><![CDATA[
* { margin: 0; padding: 0 }
html, body { width: 100%; height: 100%; background: #b4b4b4; font-size: 12px }
table { border: none; border-collapse: collapse; table-layout: fixed }
td { vertical-align: baseline; font-size: 12px }
#left-panel { position: absolute; left: 0; top: 0; bottom: 0; width: 300px; overflow: auto; background: #dee4ea }
#left-panel li.navigation { font-weight: bold; cursor: default; color: #9da8b2; line-height: 18px; background-position: 12px 5px; background-repeat: no-repeat; padding: 0 0 0 25px; background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAICAYAAAArzdW1AAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9sDEBQqGbO7BEcAAAAdaVRYdENvbW1lbnQAAAAAAENyZWF0ZWQgd2l0aCBHSU1QZC5lBwAAAKRJREFUGNN1zM0KgkAYheF3RvtXSsGyWhRNaILS7bdt11W0KgJvoPwZp0UlBPUtz3nOJw7Hk7necv5dOA2Qaazo2vZP0LEt9olCVtqQROufKNmuqBuBNAYW4QzXGX6B0bDPcjGnMQYJ8Cg12U59oSzaUJQa4IUAXMclDHwAAn/MxPMw765FZd2QRgopBWmsKCrdfhXnS/4ZYElBXdyxewN008Y8AephLAkqz613AAAAAElFTkSuQmCC) }
#left-panel li.success { color: #565b60 }
#left-panel li.failure { color: red }
#left-panel li { list-style: none; color: black; cursor: pointer }
#left-panel li.selected { background-repeat: repeat-x; color: white; background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAUCAYAAABMDlehAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9sDEBQxLTs5O2gAAAAdaVRYdENvbW1lbnQAAAAAAENyZWF0ZWQgd2l0aCBHSU1QZC5lBwAAAEdJREFUCNc1y7ERgEAMA0GNUhIyGqM2uqKgtyWZhE9v53A/7/A6D7BkMDNgy2AroB2wHTCZv5UMOgFLG1bvd7XBckBlwCXjA5wMOF5iOX/MAAAAAElFTkSuQmCC) }
#left-panel div { line-height: 20px; background-position: 25px 3px; background-repeat: no-repeat; padding: 0 0 0 45px }
#left-panel div.success { background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA8AAAAOCAYAAADwikbvAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9sDEBULEEc6wzcAAAAdaVRYdENvbW1lbnQAAAAAAENyZWF0ZWQgd2l0aCBHSU1QZC5lBwAAAiNJREFUKM99kktIVGEYhp/jzJl08lI6logp2Y2EFkbtaqlFROsWrlq4ioJWQRs37VoUVItWkYEVRGSBlhleCpywDEWxTEuxcURTZ6YzxzP/5WshCOHUt36f93kXnyMi5Lsnb4clI4s4fhkXzp5w8mWcfHBvfEpUxVdCUUU6lUPNHuD86cYtBQX5GhPrM7hRg7GaSDRg2vuUd90WuOPVsOyqy6FFo2yOQHlU1S9z9dZT+S/8I7GCLlkAN4eyAf56mnT6Fy1HLnGuuYa++MS/4e74qMRqfXLaJ9BpfnsrLC0m2BYuoqwUbj/+274JD43OEqmexwvW8NUKXnaZtVSS1pNtAAyOvyC6v48HnUNb4Z7PH8UtTlIQWA5tb2RhYY7kz3l2FleytJYg/qWb8t2KZ/0PN+1hgI6uEUr2jpHKpGlquExVaS0VbjUZL7WxaqIXK6ADQ0n9GNfv9XCttWnD/O57t0TKFklnF3g5fJ/seoaa2D4O1x0F4PlgO9oIftbgFgYMfLgjACGqj0vlsddoUnj+Kt/mxunq72RP+UGqYjWMTA7R+b6dUCSEGEF5hoJQip6BaFs4HJtCyRrKs6wHCovDip/kys0WWpovMpOYBCtoT2N9B5uzWG0Zid8gnFrVFEQDtBaUrxEgXBimaEeER2/uIiK4roPOaMRYjBKsFly3fOO3G06dETGCWIsYjckprMphtEKMAQtgsMYi1mJMQHJ6xvkDKQoyphCzkl0AAAAASUVORK5CYII=) }
#left-panel div.failure { background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA8AAAAOCAYAAADwikbvAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9sDEBUJOEC5CU8AAAAdaVRYdENvbW1lbnQAAAAAAENyZWF0ZWQgd2l0aCBHSU1QZC5lBwAAAeVJREFUKM+NkDtok2EUhp8vl9ZLo/EyKI6KFgqCKC4OClrBWUQEcRRx1cGpk3WyInWrgoMZKkW8thYaEYQ0i7WC2ngrNDTERHJvkv/L/3//dxwc7F8jeOAsh/c973OOEhG61aPnaen7maXYt4MLZ4+pbppQt+F06jNH3QWOb8pxUs+SmJzjv83hxY8SVy3wNdtVneiHqe54IhLoB4/TUkyMyOrKj5yXoVtPZK02kLyYK7OnlqFWzgcCGtUC/YUJ3n5a/jd28tU7ORTN0myUA6Jms8bpWIa798elqzn1fokjThrpVBC3ETzNbYAuca59j/Hp+b/N869Tsk8tgVMCXQk+RlfQuk1/tMLMwzsSMCcm5zjhvoR2AdpF0GuwO4aqttS05ZSbZHhsBoAIwI83Cdkd/460XDAOG02d24MxvlR8dsUUh3f2UHaEtgdbWCHz4oZwcVCp66PP5FLhKjEc8DXaCMsNy8DYn/SnZ+L0hhWOb/F8yLs9fDtwk8j+VpqwrlC34PrgGEu2bhlYhZ1b8dncq3AMeBaUr/k6NUyk4ChKzu+N2hc6Bqody+WDG8g2fLatD7F3axjPgmvAtYJvIbouhhIRrl0ZktnkBGIt1gqeMXQ8D2MMiCIUCqFEsFhEQMSykCuqX0MzLAUJTzRsAAAAAElFTkSuQmCC) }
#left-panel div.detail { display: none }
#right-panel { position: absolute; right: 0; top: 0; bottom: 0; left: 301px; overflow: auto; background: white }
#right-panel .group { font-size: 12px; font-weight: bold; line-height: 16px; padding: 0 0 0 18px; counter-reset: assertion; background-repeat: repeat-x; background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAQCAYAAADXnxW3AAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9sDEBUkDq8pxjkAAAAdaVRYdENvbW1lbnQAAAAAAENyZWF0ZWQgd2l0aCBHSU1QZC5lBwAAADdJREFUCNdVxrERwDAMAzGK0v47eS6Z927SpMFBAAbkvSvnRk5+7K5cVfLMyN39bWakJAjA5xw9R94jN3tVhVEAAAAASUVORK5CYII=) }
#right-panel .zebra { background-repeat: repeat; padding: 0 0 0 18px; background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAmCAYAAAAFvPEHAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9sDEBYWFlNztEcAAAAdaVRYdENvbW1lbnQAAAAAAENyZWF0ZWQgd2l0aCBHSU1QZC5lBwAAABdJREFUCNdjYKAtePv5338mBgYGBpoQAGy1BAJlb/y6AAAAAElFTkSuQmCC) }
#right-panel .data { line-height: 19px; white-space: nowrap }
#right-panel pre.data { white-space: pre }
#right-panel tbody.failure { color: red }
#right-panel td.key { min-width: 108px }
#right-panel td.delimiter { min-width: 18px }
#right-panel td.assertion:before { counter-increment: assertion; content: counter(assertion) ". " }
#right-panel td.assertion { color: black }
#right-panel .trail { border-top: 1px solid #b4b4b4 }
]]></style>
<script type="text/javascript"><![CDATA[
var onclick_li = (function() {
var last_selected = null;
return function(li) {
if( last_selected == li )
return;
if( last_selected )
last_selected.className = "";
last_selected = li;
last_selected.className = "selected";
document.getElementById("right-panel").innerHTML = last_selected.firstChild.nextSibling.innerHTML;
return false;
};
})();
var patch_timestamp = function() {
var spans = document.getElementsByTagName("span");
var len = spans.length;
for( var i = 0; i < len; ++i ) {
var span = spans[i];
if( "patch_timestamp" == span.className )
span.innerHTML = new Date( parseInt( span.innerHTML ) );
}
};
var patch_navigation_class = (function() {
var set_class = function(el, flag) {
if(el) {
el.className += flag ? " success" : " failure";
}
};
var traverse = function(el, group_el, flag) {
while(1) {
if(el) {
if(el.className == 'navigation') {
set_class(group_el, flag);
group_el = el;
flag = true;
} else {
var o = el.firstChild;
o = o ? o.className : null;
flag = flag ? (o == 'success') : false;
}
el = el.nextSibling;
} else {
set_class(group_el, flag);
break;
}
}
};
return function() {
var o = document.getElementById("result-list");
o = o ? o.firstChild : null;
if(o)
traverse(o, null, true);
};
})();
window.onload = function() {
patch_timestamp();
patch_navigation_class();
var o = document.getElementById("result-list");
o = o ? o.firstChild : null;
o = o ? o.nextSibling : null;
if(o)
onclick_li(o);
};
]]></script>
</head>
<body>
<div id="left-panel">
<ol id="result-list">
<xsl:for-each select="*">
<!-- group with the previous sibling -->
<xsl:if test="position() = 1 or @tn != preceding-sibling::*[1]/@tn">
<li class="navigation">Thread: <xsl:value-of select="@tn"/></li>
</xsl:if>
<li onclick="return onclick_li(this);">
<div>
<xsl:attribute name="class">
<xsl:choose>
<xsl:when test="@s = 'true'">success</xsl:when>
<xsl:otherwise>failure</xsl:otherwise>
</xsl:choose>
</xsl:attribute>
<xsl:value-of select="@lb"/>
</div><div class="detail">
<div class="group">Sampler</div>
<div class="zebra">
<table>
<tr><td class="data key">Thread Name</td><td class="data delimiter">:</td><td class="data"><xsl:value-of select="@tn"/></td></tr>
<tr><td class="data key">Timestamp</td><td class="data delimiter">:</td><td class="data"><span class="patch_timestamp"><xsl:value-of select="@ts"/></span></td></tr>
<tr><td class="data key">Time</td><td class="data delimiter">:</td><td class="data"><xsl:value-of select="@t"/> ms</td></tr>
<tr><td class="data key">Latency</td><td class="data delimiter">:</td><td class="data"><xsl:value-of select="@lt"/> ms</td></tr>
<tr><td class="data key">Bytes</td><td class="data delimiter">:</td><td class="data"><xsl:value-of select="@by"/></td></tr>
<tr><td class="data key">Sample Count</td><td class="data delimiter">:</td><td class="data"><xsl:value-of select="@sc"/></td></tr>
<tr><td class="data key">Error Count</td><td class="data delimiter">:</td><td class="data"><xsl:value-of select="@ec"/></td></tr>
<tr><td class="data key">Response Code</td><td class="data delimiter">:</td><td class="data"><xsl:value-of select="@rc"/></td></tr>
<tr><td class="data key">Response Message</td><td class="data delimiter">:</td><td class="data"><xsl:value-of select="@rm"/></td></tr>
</table>
</div>
<div class="trail"></div>
<xsl:if test="count(assertionResult) > 0">
<div class="group">Assertion</div>
<div class="zebra">
<table>
<xsl:for-each select="assertionResult">
<tbody>
<xsl:attribute name="class">
<xsl:choose>
<xsl:when test="failure = 'true'">failure</xsl:when>
<xsl:when test="error = 'true'">failure</xsl:when>
</xsl:choose>
</xsl:attribute>
<tr><td class="data assertion" colspan="3"><xsl:value-of select="name"/></td></tr>
<tr><td class="data key">Failure</td><td class="data delimiter">:</td><td class="data"><xsl:value-of select="failure"/></td></tr>
<tr><td class="data key">Error</td><td class="data delimiter">:</td><td class="data"><xsl:value-of select="error"/></td></tr>
<tr><td class="data key">Failure Message</td><td class="data delimiter">:</td><td class="data"><xsl:value-of select="failureMessage"/></td></tr>
</tbody>
</xsl:for-each>
</table>
</div>
<div class="trail"></div>
</xsl:if>
<div class="group">Request</div>
<div class="zebra">
<table>
<tr><td class="data key">Method/Url</td><td class="data delimiter">:</td><td class="data"><pre class="data"><xsl:value-of select="method"/><xsl:text> </xsl:text><xsl:value-of select="java.net.URL"/></pre></td></tr>
<tr><td class="data key">Query String</td><td class="data delimiter">:</td><td class="data"><pre class="data"><xsl:value-of select="queryString"/></pre></td></tr>
<tr><td class="data key">Cookies</td><td class="data delimiter">:</td><td class="data"><pre class="data"><xsl:value-of select="cookies"/></pre></td></tr>
<tr><td class="data key">Request Headers</td><td class="data delimiter">:</td><td class="data"><pre class="data"><xsl:value-of select="requestHeader"/></pre></td></tr>
</table>
</div>
<div class="trail"></div>
<div class="group">Response</div>
<div class="zebra">
<table>
<tr><td class="data key">Response Headers</td><td class="data delimiter">:</td><td class="data"><pre class="data"><xsl:value-of select="responseHeader"/></pre></td></tr>
<tr><td class="data key">Response Data</td><td class="data delimiter">:</td><td class="data"><pre class="data"><xsl:value-of select="responseData"/></pre></td></tr>
<tr><td class="data key">Response File</td><td class="data delimiter">:</td><td class="data"><pre class="data"><xsl:value-of select="responseFile"/></pre></td></tr>
</table>
</div>
<div class="trail"></div>
</div>
</li>
</xsl:for-each>
</ol>
</div>
<div id="right-panel"></div>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
新建文本文档-》把你上面全部代码完整复制粘贴进去-》关闭文档-》重命名文件-》文件名:jmeter.results.shanhe.me.xsl(一定要改后缀 .xsl,不要保留 .txt)
2)把jmeter.results.shanhe.me.xsl的文件拷贝到jmeter的D:\apache-jmeter-5.6.3\extras目录。

3)把jmeter的D:\apache-jmeter-5.6.3\extras目录下的ant-jmeter-1.1.1.jar拷贝到ant的lib目录


3.4、配置全局变量jmeter.propties文件
为什么需要配置jmeter.propties文件?
还记得之前我们将jmeter.save.saveservice.output_format=csv 改为了csv对吧


现在得重新改,改为xml格式,因为我们的Ant只支持格式:jmeter.save.saveservice.output_format=xml,所以修改:bin/jmeter.propties

3.5、重新打开dos窗口,然后输入ant命令执行脚本
1)定位到我们的Jmeter脚本的目录(.jmx)

2)直接输入ant命令并解释执行逻辑

3)查看结果

4)我们看html目录并点击里面的html文件看看


5)我们主要看的就是详细报告


5)信息报告中的信息修复

但是你会发现一个问题,我们的请求响应里面那些数据,他的详细信息没有显示出来。
其实就是我们之前用的bulid.xml文件缺少了一些必要的属性配置,那下面是我们修正后的正确配置模版👇
xml
<?xml version="1.0" encoding="UTF-8"?>
<project name="ant-jmeter-test" default="run" basedir=".">
<property environment="env"/>
<tstamp>
<format property="time" pattern="yyyy_MM_dd_hh_mm" />
</tstamp>
<!-- ====================== 【所有必须修改的路径,全部在这里!】 ====================== -->
<property name="jmeter.home" value="【这里填你的JMeter安装目录,例如:D:\apache-jmeter-5.6.3】" />
<property name="report.title" value="接口自动化测试"/>
<property name="jmeter.result.jtl.dir" value="【这里填jtl文件存放目录,例如:E:\ants\jtl】" />
<property name="jmeter.result.html.dir" value="【这里填汇总报告目录,例如:E:\ants\html】" />
<property name="jmeter.result.html.dir1" value="report" />
<property name="ReportName" value="接口自动化汇总报告" />
<property name="ReportName1" value="接口自动化详细报告" />
<!-- ================================================================================ -->
<property name="jmeter.result.jtlName" value="${jmeter.result.jtl.dir}/${ReportName}.jtl" />
<property name="jmeter.result.htmlName" value="${jmeter.result.html.dir}/${ReportName}.html" />
<property name="jmeter.result.htmlName1" value="${jmeter.result.html.dir1}/${ReportName1}.html" />
<target name="run">
<antcall target="test" />
<antcall target="report" />
</target>
<target name="test">
<taskdef name="jmeter" classname="org.programmerplanet.ant.taskdefs.jmeter.JMeterTask" />
<jmeter jmeterhome="${jmeter.home}" resultlog="${jmeter.result.jtlName}">
<testplans dir="【这里填你的jmx脚本所在目录,例如:E:\ants】" includes="*.jmx" />
<!-- 以下是固定配置,用来保存请求、响应详情,不要修改 -->
<property name="jmeter.save.saveservice.output_format" value="xml"/>
<property name="jmeter.save.saveservice.response_data" value="true"/>
<property name="jmeter.save.saveservice.samplerData" value="true"/>
<property name="jmeter.save.saveservice.requestHeaders" value="true"/>
<property name="jmeter.save.saveservice.responseHeaders" value="true"/>
<property name="jmeter.save.saveservice.url" value="true"/>
</jmeter>
</target>
<path id="xslt.classpath">
<fileset dir="${jmeter.home}/lib" includes="xalan*.jar"/>
<fileset dir="${jmeter.home}/lib" includes="serializer*.jar"/>
</path>
<target name="report">
<tstamp> <format property="report.datestamp" pattern="yyyy/MM/dd HH:mm" /></tstamp>
<xslt
classpathref="xslt.classpath"
force="true"
in="${jmeter.result.jtlName}"
out="${jmeter.result.htmlName}"
style="${jmeter.home}/extras/jmeter-results-report_21.xsl">
<param name="dateReport" expression="${report.datestamp}"/>
</xslt>
<xslt
classpathref="xslt.classpath"
force="true"
in="${jmeter.result.jtlName}"
out="${jmeter.result.htmlName1}"
style="${jmeter.home}/extras/jmeter.results.shanhe.me.xsl">
<param name="dateReport" expression="${report.datestamp}"/>
</xslt>
<copy todir="${jmeter.result.html.dir}">
<fileset dir="${jmeter.home}/extras">
<include name="collapse.png" />
<include name="expand.png" />
</fileset>
</copy>
<copy todir="${jmeter.result.html.dir1}">
<fileset dir="${jmeter.home}/extras">
<include name="collapse.png" />
<include name="expand.png" />
</fileset>
</copy>
</target>
</project>
我自己的👇

xml
<?xml version="1.0" encoding="UTF-8"?>
<!-- =========================================================
整个Ant构建脚本的根节点,定义项目名称、默认执行目标、当前目录
========================================================= -->
<project name="ant-jmeter-test" default="run" basedir=".">
<!-- 引入系统环境变量 -->
<property environment="env"/>
<!-- 定义时间戳格式,用于生成带时间的报告 -->
<tstamp>
<format property="time" pattern="yyyy_MM_dd_hh_mm" />
</tstamp>
<!-- =====================================================
【1、基础路径配置】:你只需要改这里的路径
===================================================== -->
<!-- JMeter的安装根目录 -->
<property name="jmeter.home" value="D:\apache-jmeter-5.6.3" />
<!-- 测试报告标题 -->
<property name="report.title" value="接口自动化测试"/>
<!-- JMeter生成jtl结果文件的存放目录 -->
<property name="jmeter.result.jtl.dir" value="E:\ants\jtl" />
<!-- 汇总HTML报告存放目录 -->
<property name="jmeter.result.html.dir" value="E:\ants\html" />
<!-- 详细HTML报告存放目录 -->
<property name="jmeter.result.html.dir1" value="report" />
<!-- 报告文件名前缀 -->
<property name="ReportName" value="接口自动化汇总报告" />
<property name="ReportName1" value="接口自动化详细报告" />
<!-- 拼接最终jtl文件完整路径 -->
<property name="jmeter.result.jtlName" value="${jmeter.result.jtl.dir}/${ReportName}.jtl" />
<!-- 拼接最终汇总报告完整路径 -->
<property name="jmeter.result.htmlName" value="${jmeter.result.html.dir}/${ReportName}.html" />
<!-- 拼接最终详细报告完整路径 -->
<property name="jmeter.result.htmlName1" value="${jmeter.result.html.dir1}/${ReportName1}.html" />
<!-- =====================================================
【2、总执行入口】:默认执行run目标,先跑测试,再生成报告
===================================================== -->
<target name="run">
<!-- 调用test目标执行JMeter脚本 -->
<antcall target="test" />
<!-- 调用report目标生成测试报告 -->
<antcall target="report" />
</target>
<!-- =====================================================
【3、执行JMeter性能测试脚本】⭐⭐⭐【核心配置区】⭐⭐⭐
===================================================== -->
<target name="test">
<!-- 定义Ant调用JMeter任务的类(固定写法) -->
<taskdef name="jmeter" classname="org.programmerplanet.ant.taskdefs.jmeter.JMeterTask" />
<!-- 执行JMeter命令,指定JMeter目录和结果文件输出路径 -->
<jmeter jmeterhome="${jmeter.home}" resultlog="${jmeter.result.jtlName}">
<!-- 指定要运行的.jmx脚本:扫描E:\ants目录下所有脚本 -->
<testplans dir="E:\ants" includes="*.jmx" />
<!-- =====================================================
⭐⭐⭐【你之前缺失的关键配置:开启数据保存】⭐⭐⭐
以下配置作用:让JMeter把【请求、响应、头、参数】全部写入jtl文件
不加这些,你的详细报告永远是空的!!!
===================================================== -->
<!-- 输出格式为XML(必须,报告解析需要) -->
<property name="jmeter.save.saveservice.output_format" value="xml"/>
<!-- 保存响应数据(Response Data)→ 你截图空白的核心 -->
<property name="jmeter.save.saveservice.response_data" value="true"/>
<!-- 保存请求样本数据 -->
<property name="jmeter.save.saveservice.samplerData" value="true"/>
<!-- 保存请求头(Request Headers) -->
<property name="jmeter.save.saveservice.requestHeaders" value="true"/>
<!-- 保存响应头(Response Headers) -->
<property name="jmeter.save.saveservice.responseHeaders" value="true"/>
<!-- 保存请求URL -->
<property name="jmeter.save.saveservice.url" value="true"/>
</jmeter>
</target>
<!-- =====================================================
【4、XSLT解析依赖路径】:生成HTML报告需要的jar包
===================================================== -->
<path id="xslt.classpath">
<!-- 引入JMeter自带的xalan解析器 -->
<fileset dir="${jmeter.home}/lib" includes="xalan*.jar"/>
<!-- 引入序列化工具包 -->
<fileset dir="${jmeter.home}/lib" includes="serializer*.jar"/>
</path>
<!-- =====================================================
【5、生成HTML测试报告】:汇总报告 + 详细报告
===================================================== -->
<target name="report">
<!-- 报告头部显示的时间 -->
<tstamp> <format property="report.datestamp" pattern="yyyy/MM/dd HH:mm" /></tstamp>
<!-- =====================================================
生成【汇总报告】(简洁版)
使用JMeter官方默认模板
===================================================== -->
<xslt
classpathref="xslt.classpath"
force="true"
in="${jmeter.result.jtlName}"
out="${jmeter.result.htmlName}"
style="${jmeter.home}/extras/jmeter-results-report_21.xsl">
<param name="dateReport" expression="${report.datestamp}"/>
</xslt>
<!-- =====================================================
生成【详细报告】(完整版)
使用你自定义的美化模板
===================================================== -->
<xslt
classpathref="xslt.classpath"
force="true"
in="${jmeter.result.jtlName}"
out="${jmeter.result.htmlName1}"
style="${jmeter.home}/extras/jmeter.results.shanhe.me.xsl">
<param name="dateReport" expression="${report.datestamp}"/>
</xslt>
<!-- =====================================================
拷贝报告需要的图标文件
===================================================== -->
<!-- 拷贝图标到汇总报告目录 -->
<copy todir="${jmeter.result.html.dir}">
<fileset dir="${jmeter.home}/extras">
<include name="collapse.png" />
<include name="expand.png" />
</fileset>
</copy>
<!-- 拷贝图标到详细报告目录 -->
<copy todir="${jmeter.result.html.dir1}">
<fileset dir="${jmeter.home}/extras">
<include name="collapse.png" />
<include name="expand.png" />
</fileset>
</copy>
</target>
</project>

然后我们再重新打开dos窗口,进行执行,👇

然后我们重新打开我们的详细报告看一下👇

此时报告上就会有详细信息👇

一旦有这些详细信息,包括我们的调试,我们也核心看这些信息。

上述就是我们用JMeter集成Ant来生成我们接口测试的报告,但是这种报告相对来说是一般的,我们现在做接口自动化用的最多的是Allure报告,而我们的JMeter它也能够集成Allure报告,我们接下来看👇
三、精通Jmeter接口测试集成Ant生成Allure报告
那么如何集成呢?步骤是什么呢?不要着急,跟着我的步骤一步一步的做,一定能做成功。
1、下载Allure并解压,解压后把allure的bin目录配置到PATH目录
这一步的话跟我们上述的ant差不多,反正就是下载压缩包,然后解压,然后再配置bin目录到我们的PATH目录中去,到时候执行相应的命令的时候,我们的操作系统能够找得到。
1.1、下载
下载地址:https://github.com/allure-framework/allure2/releases
版本要求:2.24以上


1.2、解压


1.3、配置环境变量

验证是否成功:

2、安装Allure报告的依赖库:allure-pytest
如何去安装呢?在我们的dos窗口里面输入以下命令:
bash
pip install allure-pytest

3、配置ant的编译文件build.xml以及jmeter2allure.py文件
3.1、ant的编译文件build.xml
xml
<!-- =====================================================
Ant 项目配置:
name:项目名称
basedir=".":脚本当前目录
default="execute-scripts":默认执行的任务
===================================================== -->
<project name="ShellScriptExecution" basedir="." default="execute-scripts">
<!-- ====================== 【必须修改的3个路径】 ====================== -->
<!-- JMeter 安装根目录 -->
<property name="jmeter.home" value="【这里填你的JMeter安装路径】"/>
<!-- Allure 报告工具安装目录 -->
<property name="allure.home" value="【这里填你的Allure安装路径】"/>
<!-- Python 安装目录(必须是python.exe所在目录) -->
<property name="python.home" value="【这里填你的Python安装路径】"/>
<!-- ====================== 以下内容 无需修改 ====================== -->
<!-- 定义Ant调用JMeter任务的插件(固定写法) -->
<taskdef
name="jmeter"
classname="org.programmerplanet.ant.taskdefs.jmeter.JMeterTask"/>
<!-- =====================================================
任务1:clear
作用:清空旧的测试文件,防止旧数据干扰
删除:旧的result.jtl结果文件 + report报告目录
===================================================== -->
<target name="clear">
<delete file="result.jtl"/>
<delete dir="report"/>
</target>
<!-- =====================================================
任务2:runJMeter
作用:执行当前目录下所有 .jmx 结尾的JMeter脚本
生成结果文件:result.jtl
自动开启请求/响应数据保存(保证Allure报告有详情)
===================================================== -->
<target name="runJMeter">
<jmeter jmeterhome="${jmeter.home}" resultlog="result.jtl">
<!-- 执行当前目录下所有jmx脚本 -->
<testplans dir="./" includes="*.jmx"/>
<!-- 固定配置:保存请求、响应、Header,让报告有详情 -->
<property name="jmeter.save.saveservice.output_format" value="xml"/>
<property name="jmeter.save.saveservice.response_data" value="true"/>
<property name="jmeter.save.saveservice.samplerData" value="true"/>
<property name="jmeter.save.saveservice.requestHeaders" value="true"/>
<property name="jmeter.save.saveservice.responseHeaders" value="true"/>
</jmeter>
</target>
<!-- =====================================================
任务3:makeAllure
作用:调用python工具,把jtl文件转换成Allure报告
===================================================== -->
<target name="makeAllure">
<exec executable="cmd" dir="${basedir}">
<arg value="/c"/> <!-- 执行cmd命令 -->
<arg value="${python.home}/python.exe"/> <!-- 调用Python -->
<arg value="-m"/> <!-- 运行模块 -->
<arg value="jmeter2allure"/> <!-- jtl转allure工具 -->
<arg value="result.jtl"/> <!-- 输入结果文件 -->
<arg value="report"/> <!-- 输出报告目录 -->
<arg value="${allure.home}/bin/allure"/> <!-- allure命令路径 -->
</exec>
</target>
<!-- =====================================================
总入口任务:execute-scripts
执行顺序:先清空 → 再运行JMeter → 最后生成Allure报告
===================================================== -->
<target name="execute-scripts" depends="clear,runJMeter,makeAllure">
</target>
</project>
3.1、jmeter2allure.py文件
py
# ==========================================
# 脚本功能:
# JMeter 的 .jtl 结果文件 → 自动转成 Allure 精美HTML报告
# 实现:读取jtl → 生成pytest测试用例 → 运行 → 生成Allure单页报告
# ==========================================
"""
# 依赖安装命令(只需要装一次)
pip install pytest allure-pytest -i https://pypi.tuna.tsinghua.edu.cn/simple/
"""
# 导入Python解析XML的库
import xml.etree.cElementTree as ET
# 导入json、操作系统、唯一ID、系统参数、文件路径库
import json, os, uuid, sys
from pathlib import Path
# ==========================================
# 核心递归函数:遍历JMeter的jtl(XML)文件
# 读取:接口名称、请求、响应、断言、模块、功能模块
# 自动生成 pytest + allure 测试用例代码
# ==========================================
def checkChildren(
xmlObject, # XML节点对象
checkString, # 要查找的节点:httpSample
num, # 层级编号
result, # 存放解析出来的结果
demoFile, # 要生成的.py文件路径
featureIndex, # 一级模块编号
storyIndex # 二级模块编号
):
# 遍历XML所有子节点
for children in xmlObject:
try:
# 第一层:解析一级模块(feature)
if num == 1 and children.attrib["sby"] != "0":
featureIndexStr = "#" + str(featureIndex) + " " if featureIndex >= 10 else "#0" + str(featureIndex) + " "
result["feature"] = featureIndexStr + children.attrib["lb"]
featureIndex += 1
# 第二层及以下:解析二级模块(story)
if num >= 2 and children.tag == "sample":
storyIndexStr = "#" + str(storyIndex) + " " if storyIndex >= 10 else "#0" + str(storyIndex) + " "
result["story"] = storyIndexStr + children.attrib["lb"]
storyIndex += 1
except:
pass
# ==========================================
# 找到接口节点 httpSample,开始解析数据
# ==========================================
if children.tag == checkString:
# 用例名称
result["case_name"] = children.attrib["lb"]
# 遍历接口的请求头、响应头、请求体、响应体、断言
for httpSampleChildren in children:
result[httpSampleChildren.tag] = httpSampleChildren.text
# 如果是断言结果,单独解析
if httpSampleChildren.tag == "assertionResult":
for assertionResultChildren in httpSampleChildren:
result[assertionResultChildren.tag] = assertionResultChildren.text
# ==========================================
# 从解析结果中取出需要展示到报告里的字段
# ==========================================
feature = result.get("feature") # 一级模块
story = result.get("story") # 二级模块
case_name = result.get("case_name") # 用例名称
URL = result.get("java.net.URL") # 请求URL
method = result.get("method") # 请求方法
requestHeader = result.get("requestHeader") # 请求头
queryString = result.get("queryString") # 请求参数
responseData = result.get("responseData") # 响应数据
failureMessage = result.get("failureMessage") # 失败信息
failure = result.get("failure", "false") # 是否失败
# ==========================================
# 拼接 Allure 测试用例代码(字符串)
# ==========================================
storyString = f"@allure.story('{story}') # 二级目录" if story else ""
pyString = f"""
@allure.feature('{feature}') # 一级目录{storyString}
@allure.title("{case_name}")
def test_allure_report_{str(uuid.uuid1()).replace('-', '')}():
with allure.step('请求url:{URL}'):
print('请求url:{URL}')
with allure.step('请求方法:{method}'):
print('请求方法:{method}')
with allure.step('请求头:{requestHeader}'):
print('请求头:{requestHeader}')
with allure.step('''请求数据:{queryString}'''):
print('''请求数据:{queryString}''')
with allure.step('''接口返回:{responseData}'''):
print('''接口返回:{responseData}''')
with allure.step('''断言结果:{failureMessage}'''):
print('''断言结果:{failureMessage}''')
assert "{failure}" == 'false'
"""
# ==========================================
# 把生成的用例写入 .py 文件
# ==========================================
with open(demoFile, "a", encoding="utf-8") as c:
c.write(pyString)
# 递归继续查找子节点
else:
checkChildren(
children,
checkString,
num + 1,
result,
demoFile,
featureIndex,
storyIndex,
)
# ==========================================
# 主函数入口
# ==========================================
if __name__ == "__main__":
# 接收命令行参数:python 脚本.py jtl文件 报告目录 allure路径
_self_path, jtl_path, report_path, allure_path, *_ = sys.argv
# 路径转换为Path对象(方便操作)
jtl_path = Path(jtl_path)
report_path = Path(report_path)
report_resource = report_path / "resource" # allure原始数据
report_html = report_path / "html" # 最终HTML报告
tmp_file_path = Path("test.py") # 临时生成的pytest用例文件
# ==========================================
# 1. 创建临时 test.py 文件,写入头部引用
# ==========================================
with open(tmp_file_path, "w", encoding="utf-8") as demo:
demo.write("""
# -*- coding: utf-8 -*-
import allure
""")
# ==========================================
# 2. 解析 jtl XML 文件
# ==========================================
tree = ET.parse(str(jtl_path))
root = tree.getroot()
# ==========================================
# 3. 调用递归函数,遍历XML生成测试用例
# ==========================================
checkChildren(root, "httpSample", 1, {}, str(tmp_file_path), 1, 1)
# ==========================================
# 4. 执行 pytest 生成 allure 原始数据
# ==========================================
pyString = f"{sys.executable} -m pytest --capture=sys {tmp_file_path} --alluredir {report_resource} --clean-alluredir -qq"
os.system(pyString)
# ==========================================
# 5. 调用 allure 生成 单页HTML报告
# ==========================================
alSring = f"{allure_path} generate {report_resource} -o {report_html} --single-file --clean"
os.system(alSring)
# ==========================================
# 6. 删除临时 test.py 文件
# ==========================================
tmp_file_path.unlink(True)
# ==========================================
# 7. 自动打开生成好的报告
# ==========================================
os.system(f'{report_html / "index.html"}')
3.3、实操
两个文件必须放在【JMeter 脚本(.jmx)所在的同一个目录】!
1)首先在我们的脚本同级目录新建一个bulid.xml(名字必须严格这样)

2)将上述xml内容拷贝进去并做配置
我自己的配置如下:


那么python的目录怎么获取?如下👇输入where python


代码
xml
<!-- =====================================================
Ant 项目配置:
name:项目名称
basedir=".":脚本当前目录
default="execute-scripts":默认执行的任务
===================================================== -->
<project name="ShellScriptExecution" basedir="." default="execute-scripts">
<!-- ====================== 【必须修改的3个路径】 ====================== -->
<!-- JMeter 安装根目录 -->
<property name="jmeter.home" value="D:\apache-jmeter-5.6.3"/>
<!-- Allure 报告工具安装目录 -->
<property name="allure.home" value="D:\allure-2.39.0"/>
<!-- Python 安装目录(必须是python.exe所在目录) -->
<property name="python.home" value="D:\PythonProject"/>
<!-- ====================== 以下内容 无需修改 ====================== -->
<!-- 定义Ant调用JMeter任务的插件(固定写法) -->
<taskdef
name="jmeter"
classname="org.programmerplanet.ant.taskdefs.jmeter.JMeterTask"/>
<!-- =====================================================
任务1:clear
作用:清空旧的测试文件,防止旧数据干扰
删除:旧的result.jtl结果文件 + report报告目录
===================================================== -->
<target name="clear">
<delete file="result.jtl"/>
<delete dir="report"/>
</target>
<!-- =====================================================
任务2:runJMeter
作用:执行当前目录下所有 .jmx 结尾的JMeter脚本
生成结果文件:result.jtl
自动开启请求/响应数据保存(保证Allure报告有详情)
===================================================== -->
<target name="runJMeter">
<jmeter jmeterhome="${jmeter.home}" resultlog="result.jtl">
<!-- 执行当前目录下所有jmx脚本 -->
<testplans dir="./" includes="*.jmx"/>
<!-- 固定配置:保存请求、响应、Header,让报告有详情 -->
<property name="jmeter.save.saveservice.output_format" value="xml"/>
<property name="jmeter.save.saveservice.response_data" value="true"/>
<property name="jmeter.save.saveservice.samplerData" value="true"/>
<property name="jmeter.save.saveservice.requestHeaders" value="true"/>
<property name="jmeter.save.saveservice.responseHeaders" value="true"/>
</jmeter>
</target>
<!-- =====================================================
任务3:makeAllure
作用:调用python工具,把jtl文件转换成Allure报告
===================================================== -->
<target name="makeAllure">
<exec executable="cmd" dir="${basedir}">
<arg value="/c"/> <!-- 执行cmd命令 -->
<arg value="${python.home}/python.exe"/> <!-- 调用Python -->
<arg value="-m"/> <!-- 运行模块 -->
<arg value="jmeter2allure"/> <!-- jtl转allure工具 -->
<arg value="result.jtl"/> <!-- 输入结果文件 -->
<arg value="report"/> <!-- 输出报告目录 -->
<arg value="${allure.home}/bin/allure"/> <!-- allure命令路径 -->
</exec>
</target>
<!-- =====================================================
总入口任务:execute-scripts
执行顺序:先清空 → 再运行JMeter → 最后生成Allure报告
===================================================== -->
<target name="execute-scripts" depends="clear,runJMeter,makeAllure">
</target>
</project>
3)在脚本(.jmx)同级目录下创建jmeter2allure.py文件

4)将上述的jmter2allure.py文件代码粘贴进去

4、重新打开dos窗口,然后输入ant命令执行脚本
4.1、切换到对应的目录

4.2、输入ant命令并解释逻辑

4.3、执行ant命令看结果
1)错误排查

2)错误修改

3)修改之后的正确结果


4)出现问题
从上面的图我们也可以看出,我们这个报告里面又没有任何数据,甚至有乱码。那这是我们之前的代码配置错误,我们做了如下修改。
a.修改之后的通用模版build.xml
xml
<?xml version="1.0" encoding="UTF-8"?>
<!-- ============================================================
Ant 通用模板:JMeter 自动化执行 + Allure 报告生成
使用方法:只修改【用户配置区】3 个路径,其余不动
============================================================= -->
<project name="ShellScriptExecution" basedir="." default="execute-scripts">
<!-- ===================== 【用户配置区】请根据自己电脑修改 ===================== -->
<!-- JMeter 安装路径 -->
<property name="jmeter.home" value="【这里填JMeter安装路径】"/>
<!-- Allure 安装路径 -->
<property name="allure.home" value="【这里填Allure安装路径】"/>
<!-- Python 安装路径 -->
<property name="python.home" value="【这里填Python安装路径】"/>
<!-- ===================== 【固定配置】以下无需修改 ===================== -->
<taskdef
name="jmeter"
classname="org.programmerplanet.ant.taskdefs.jmeter.JMeterTask"/>
<target name="clear">
<delete file="result.jtl"/>
<delete dir="report"/>
</target>
<target name="runJMeter">
<jmeter jmeterhome="${jmeter.home}" resultlog="result.jtl">
<testplans dir="./" includes="*.jmx"/>
</jmeter>
</target>
<target name="makeAllure">
<exec executable="cmd" dir="${basedir}">
<arg value="/c"/>
<arg value="${python.home}/python.exe"/>
<arg value="-m"/>
<arg value="jmeter2allure"/>
<arg value="result.jtl"/>
<arg value="report"/>
<arg value="${allure.home}/bin/allure"/>
</exec>
</target>
<target name="execute-scripts" depends="clear,runJMeter,makeAllure">
</target>
</project>
b.修改之后我自己的build.xml
xml
<?xml version="1.0" encoding="UTF-8"?>
<!-- ============================================================
Ant 构建脚本:自动化执行 JMeter 测试 + 生成 Allure 测试报告
专属个人版(已配置你本机路径)
============================================================= -->
<project name="ShellScriptExecution" basedir="." default="execute-scripts">
<!-- ===================== 【个人路径配置】仅这里需要根据自己电脑修改 ===================== -->
<!-- JMeter 安装根目录 -->
<property name="jmeter.home" value="D:\apache-jmeter-5.6.3"/>
<!-- Allure 报告工具安装目录 -->
<property name="allure.home" value="D:\allure-2.39.0"/>
<!-- Python 安装目录(必须是 python.exe 所在目录) -->
<property name="python.home" value="D:\PythonProject"/>
<!-- ===================== 【固定配置】以下内容无需修改 ===================== -->
<!-- 注册 JMeter 任务插件,让 Ant 能调用 JMeter 执行脚本 -->
<taskdef
name="jmeter"
classname="org.programmerplanet.ant.taskdefs.jmeter.JMeterTask"/>
<!-- ===================== 目标1:clear ===================== -->
<!-- 作用:清空历史生成文件,避免旧数据干扰 -->
<target name="clear">
<!-- 删除旧的 jtl 结果文件 -->
<delete file="result.jtl"/>
<!-- 删除旧的 report 报告目录 -->
<delete dir="report"/>
</target>
<!-- ===================== 目标2:runJMeter ===================== -->
<!-- 作用:执行当前目录下所有 .jmx 脚本,生成 result.jtl 结果文件 -->
<target name="runJMeter">
<jmeter jmeterhome="${jmeter.home}" resultlog="result.jtl">
<!-- 匹配执行当前目录所有 jmx 文件 -->
<testplans dir="./" includes="*.jmx"/>
</jmeter>
</target>
<!-- ===================== 目标3:makeAllure ===================== -->
<!-- 作用:调用 Python 模块 jmeter2allure 解析 jtl,生成 Allure 报告 -->
<target name="makeAllure">
<exec executable="cmd" dir="${basedir}">
<!-- 打开 cmd 执行命令 -->
<arg value="/c"/>
<!-- 使用你配置的 Python 解释器 -->
<arg value="${python.home}/python.exe"/>
<!-- 以模块方式运行 jmeter2allure -->
<arg value="-m"/>
<arg value="jmeter2allure"/>
<!-- 传入参数1:jtl 结果文件 -->
<arg value="result.jtl"/>
<!-- 传入参数2:报告输出目录 -->
<arg value="report"/>
<!-- 传入参数3:allure 命令路径 -->
<arg value="${allure.home}/bin/allure"/>
</exec>
</target>
<!-- ===================== 总执行入口 ===================== -->
<!-- 执行顺序:清空 → 运行JMeter → 生成报告 -->
<target name="execute-scripts" depends="clear,runJMeter,makeAllure">
</target>
</project>
c.修改之后的jmeter2allure.py
py
# -*- coding: utf-8 -*-
"""
============================================================
JMeter jtl 结果文件 转 Allure HTML 测试报告
功能:
1. 解析 JMeter 生成的 .jtl 文件
2. 自动生成 pytest + allure 测试用例
3. 调用 pytest 运行用例
4. 调用 allure 生成 HTML 报告
============================================================
【依赖安装】
pip install pytest allure-pytest -i https://pypi.tuna.tsinghua.edu.cn/simple/
"""
# 导入 XML 解析库,用于解析 jtl 文件
import xml.etree.cElementTree as ET
# 用于处理字符串、JSON 转义
import json
# 用于执行系统命令
import os
# 用于生成唯一不重复的用例名
import uuid
# 用于获取命令行参数
import sys
# 用于路径处理
from pathlib import Path
def checkChildren(
xmlObject, checkString, num, result, demoFile, featureIndex, storyIndex
):
"""
递归函数:遍历 XML 节点,解析出接口、模块、用例、请求、响应、断言
:param xmlObject: 当前 XML 节点
:param checkString: 要匹配的节点名称(httpSample)
:param num: 递归层级
:param result: 存储解析结果
:param demoFile: 要生成的测试用例文件路径
:param featureIndex: 一级模块编号
:param storyIndex: 二级用例编号
"""
# 遍历当前节点下所有子节点
for children in xmlObject:
try:
# 第一层节点:解析 一级模块(feature)
if num == 1 and children.attrib["sby"] != "0":
# 格式化模块编号
featureIndexStr = "#" + str(featureIndex) + " " if featureIndex >= 10 else "#0" + str(featureIndex) + " "
result["feature"] = featureIndexStr + children.attrib["lb"]
featureIndex += 1
# 第二层及以下:解析 二级用例(story)
if num >= 2 and children.tag == "sample":
storyIndexStr = "#" + str(storyIndex) + " " if storyIndex >= 10 else "#0" + str(storyIndex) + " "
result["story"] = storyIndexStr + children.attrib["lb"]
storyIndex += 1
except:
# 异常忽略,不影响整体解析
pass
# 匹配到接口请求节点 httpSample,开始解析接口数据
if children.tag == checkString:
# 用例名称
result["case_name"] = children.attrib["lb"]
# 遍历接口的请求头、响应头、请求体、响应体、断言
for httpSampleChildren in children:
result[httpSampleChildren.tag] = httpSampleChildren.text
# 如果是断言结果,单独解析
if httpSampleChildren.tag == "assertionResult":
for assertionResultChildren in httpSampleChildren:
result[assertionResultChildren.tag] = assertionResultChildren.text
# 安全取值:存在则取,不存在为 None
feature = result["feature"] if "feature" in result else None
story = result["story"] if "story" in result else None
case_name = result["case_name"] if "case_name" in result else None
URL = result["java.net.URL"] if "java.net.URL" in result else None
method = result["method"] if "method" in result else None
requestHeader = result["requestHeader"] if "requestHeader" in result else None
queryString = result["queryString"] if "queryString" in result else None
responseData = result["responseData"] if "responseData" in result else None
failureMessage = result["failureMessage"] if "failureMessage" in result else None
failure = result["failure"] if "failure" in result else "false"
# 优化断言结果显示
if failure == "false":
failureMessage = "断言成功"
elif not failureMessage or failureMessage.strip() == "":
failureMessage = "断言失败(无详细信息)"
# 拼接 allure 二级目录注解
storyString = "@allure.story('" + result["story"] + "') # 二级目录" if "story" in result else ""
# ===================== 生成 pytest + allure 用例代码 =====================
pyString = """
@allure.feature('{feature}') # 一级目录{story}
@allure.title("{case_name}")
def test_allure_report_{num}():
with allure.step('请求url:{URL}'):
print('请求url:{URL}')
with allure.step('请求方法:{method}' ):
print('请求方法:{method}' )
with allure.step('请求头:{requestHeader}' ):
print('请求头:{requestHeader}' )
with allure.step('''请求数据:{queryString}'''):
print('''请求数据:{queryString}''')
with allure.step('''接口返回:{responseData}'''):
print('''接口返回:{responseData}''')
with allure.step('''断言结果:{failureMessage}'''):
print('''断言结果:{failureMessage}''')
assert "{failure}" == 'false' """.format(
feature=feature,
story=storyString,
case_name=case_name,
num=str(uuid.uuid1()).replace("-", ""),
URL=URL,
method=method,
requestHeader=str(requestHeader).replace("\n", "").replace("\r", ""),
queryString=str(json.dumps(queryString)).replace("'", '"'),
responseData=str(json.dumps(responseData)).replace("'", '"'),
failureMessage=str(failureMessage).replace("'", '"'),
failure=failure,
)
# 将生成的用例写入测试文件
with open(demoFile, "a", encoding="utf-8") as c:
c.write(pyString)
else:
# 递归继续解析子节点
checkChildren(
children,
checkString,
num + 1,
result,
demoFile,
featureIndex,
storyIndex,
)
if __name__ == "__main__":
"""
主函数入口
命令格式:python jmeter2allure.py 结果文件.jtl 报告目录 allure路径
"""
# 获取命令行传入的 4 个参数
_self_path, jtl_path, report_path, allure_path, *_ = sys.argv
# 路径转换
jtl_path = Path(jtl_path)
report_path = Path(report_path)
# allure 原始数据存放目录
report_resource = report_path / "resource"
# 最终 HTML 报告目录
report_html = report_path / "html"
# 临时生成的 pytest 用例文件
tmp_file_path = Path("test.py")
# 初始化临时用例文件,写入导包
with open(tmp_file_path, "w", encoding="utf-8") as demo:
demo.write("""
# -*- coding: utf-8 -*-
import allure
""")
# 解析 jtl 文件
tree = ET.parse(str(jtl_path))
root = tree.getroot()
# 递归解析 jtl,生成测试用例
checkChildren(root, "httpSample", 1, {}, str(tmp_file_path), 1, 1)
# ===================== 执行 pytest,生成 allure 原始数据 =====================
pyString = f"{sys.executable} -m pytest --capture=sys {tmp_file_path} --alluredir {report_resource} --clean-alluredir -qq"
os.system(pyString)
# ===================== 生成 HTML 报告 =====================
alSring = f"{allure_path} generate {report_resource} -o {report_html} --single-file --clean"
os.system(alSring)
# 删除临时用例文件
tmp_file_path.unlink(True)
# 自动打开生成的报告
os.system(f'{report_html / "index.html"}')
4.4、删除多余的文件重启dos窗口运行看结果


接下来解决详细信息的问题
4.5、解决没有详细信息问题
1)找到 JMeter 安装目录下的 bin/jmeter.properties,用文本编辑器打开,修改或添加以下配置项:
bash
# 1. 输出格式必须为 XML(这个我们之前配置过了,此处不用管)
jmeter.save.saveservice.output_format=xml
# 2. 保存断言结果(用于记录失败原因)
jmeter.save.saveservice.assertion_results=all
jmeter.save.saveservice.assertion_results_failure_message=true
# 3. 保存请求 URL
jmeter.save.saveservice.url=true
# 4. 保存请求方法(GET/POST 等)
jmeter.save.saveservice.method=true # 注意:您的片段里没有 method 这一行?如果缺了需手动添加
# 5. 保存请求主体数据(含表单、JSON、文件上传的元数据)
jmeter.save.saveservice.samplerData=true
# 6. 保存查询字符串(GET 参数)
jmeter.save.saveservice.queryString=true
# 7. 保存请求头
jmeter.save.saveservice.requestHeaders=true
# 8. 保存响应数据(接口返回的正文)
jmeter.save.saveservice.response_data=true
# 9. 保存响应头(可选,但有助于调试)
jmeter.save.saveservice.responseHeaders=true


2)重新运行ant查看结果

5、补充

现在如果想要手动打开报告的话,就去report目录的html目录中打开

四、精通Jmeter接口测试Jenkins持续集成
其实无论是我们的ant报告,还是我们的allure报告,我们的最终目的都是为了给我们的Jenkins持续集成。
那么如何去Jenkins持续集成,接下里就跟着我一步一步的实现。
1、安装Jenkins,建议去官网安装最新版本
1.1 下载
官网地址: https://www.jenkins.io/download/
Jenkins是一个web项目


兼容性问题:由于Jenkins是一个javaweb项目,那么得需要jdk,建议jdk要17及以上。
1.2 启动服务并访问
启动
对一个java项目,我们如何去启动呢?它是一个war包,那么我只需要运行这个war包就行。
1)首先得看你的jdk有没有下载配置好

java项目的运行需要的是jdk,这一点很重要,没有java环境的老铁得去配置一下,我们之前第一篇博客有说过。
2)运行war包,命令:java -jar 全路径+war包名称(带后缀)
比如我自己的是放在D盘,所以启动命令java -jar D:\jenkins.war

3)那么我就将jdk21下载好了,放在如下目录D:\java\Javajdk\jdk-21

4)去bin目录找到java命令

5)然后执行"jdk21的bin目录+java" -jar war包全路径+war包名称
比如我自己的是:"D:\java\Javajdk\jdk-21\bin\java" -jar D:\jenkins.war

访问
如何访问呢?
浏览器输入访问地址:http://localhost:8080
初始化密码,你启动的时候他会给你显示。
用户名默认是admin
密码初始话的时候如下图:

1)输入URL访问:http://localhost:8080

2)会告诉你是否安装插件

1.3 初始化安装插件
首先第一次登录的时候可以选择推荐的

然后他就在下载

把上述的插件安装完毕之后,他会给你一个提示框,让你创建一个管理员用户👇
1.4 修改密码👤

如果你不想创建,你就直接点使用admin账户继续就行,如上图所示:
然后后面就直接点击继续


修改密码:如下所示

然后我们就输入自己的密码即可比如123456

修改密码之后重新登录:
用户名admin
密码123456

1.5 修改插件的下载位置(可选)
下载完插件之后,你会发现在你的c盘里面会多了一些目录,这些目录就是为我们放我们插件的创建的,那如果你c盘空间不够的话,我们是可以进行一个修改的。如何去修改呢?接下来就跟着我一步一步的去做就行。嗯,如果老铁们嫌麻烦的话,就可以不用管这个步骤。
1). 停止当前运行的 Jenkins
- 关闭运行
java -jar jenkins.war的命令行窗口(按Ctrl + C或直接关闭)。
2). 迁移原有数据(可选)
如果你已经使用过 Jenkins(创建了任务、安装了插件),需要把旧数据复制到新目录。
- 旧目录:
C:\Users\用户名\.jenkins - 新目录(例子):
D:\jenkins_home
操作:
- 在 D 盘创建文件夹
jenkins_home - 将
C:\Users\用户名\.jenkins下的所有内容 复制到D:\jenkins_home(包括config.xml、plugins、workspace等)
如果 Jenkins 是全新安装(刚跑通初始化),可以不用复制旧数据,直接让 Jenkins 在新目录重新初始化。
3). 启动时指定新的家目录
方法:修改系统环境变量(永久)
- 右键"此电脑" → 属性 → 高级系统设置 → 环境变量
- 在"系统变量"或"用户变量"中新建:
- 变量名:
JENKINS_HOME - 变量值:
D:\jenkins_home
- 变量名:
- 确定后重启 cmd,直接运行
"D:\java\Javajdk\jdk-21\bin\java" -jar D:\jenkins.war就会自动使用该目录。


Jenkins 现在已经成功将家目录迁移到 D:\jenkins_home
1.6 下载HTML报告的插件和Allure报告的插件
具体步骤
1、选择设置

2、在 Manage Jenkins 页面中,点击 "插件管理" (图标是拼图块,文字是"添加、删除、禁用或启用Jenkins功能扩展插件")。

3、进入插件管理页面后,点击 "Available plugins" (可用插件)选项卡。

4、在右上角的搜索框中分别搜索以下两个插件,并勾选:
-
HTML Publisher→ 找到 HTML Publisher ,勾选。
-
Allure→ 找到 Allure ,勾选。
安装完成后验证


注意:Jenkins得通过插件才能完成后续的操作,所以你得下载插件
况且很多的插件你是需要做配置的,那么怎么去配置如下所示👇
2、插件配置
我们并不是说有些插件你下载之后就是可以直接使用,而是需要做一些配置,比如我们的Allure需要配置才能使用,而且这种情况核心的配置步骤我们可以问AI很快就能做完。
当然我们的html报告插件是不需要配置的。
你看有些插件需要配置,有些插件不需要配置,那你如何去判断,他们需不需要配置呢?👇
对于不确定的插件,可以问AI:"Jenkins 的 [插件名] 插件安装后需要额外配置吗?怎么配置?"
那么接下来我们就对Allure插件进行配置
Allure插件配置
步骤如下:
由于Jenkins 我们的这个版本不断的在更新,所以到时候如果没有出现过如下所示的界面,那大家可以问AI。
1) 点击设置

2)点击全局工具配置

3)往下翻找到【Allure Commandline 安装】

4)点击【+新增Allure Commandline】然后起一个别名

5)然后他问你是否需要自动安装,那把那个√给去掉,我们不需要自动安装,因为我们的本地已经装好了。

6)在本地将我们的allure安装路径给复制上去,并保存

从这个过程我们也看到一个小规律,就是说你这些工具是需要下载到本地的,然后我们所谓的配置无非就是把本地的安装路径给配置上去而已,所以需不需要配置,就得看你这个工具是否需要下载。
接下来我们就可以使用Jenkins执行我们的Jmeter测试脚本了,然后生成对应的报告👇
3、Jenkins的配置
还是一样的,跟我一步一步的做,如果界面跟我不同,那就问AI,因为他版本在更新。
3.1 点击【+新建Item】

3.2 起一个名字

3.3 选择任务类型:自由风格的(Freestyle project)

于是会来到这个界面

3.4 做项目(任务)配置:点击高级,勾选自定义工作空间

为什么我们要设置自己的工作空间呢?
因为我们想让Jenkins这个工具为我们去执行jmeter的测试脚本,所以你得告诉他你的测试脚本在哪里,如果你不告诉他他去执行什么呢,对吧?同时到时候我们生成的测试报告会让他放到我们工作空间中去(而里面的具体目录就是我们的bulix.xml那些文件所去指定的操作。)
3.5 指定Jmeter测试脚本所在的目录

3.6 点击【增加构建步骤】:选择执行windows的批处理命令并输入执行的命令

然后输入我们要执行的命令,我们要执行的命令很简单:ant👇

3.7 点击保存之后呢,我们会跳到如下界面【开始执行】
1)保存

2)保存后跳转如下👇

3)首页

4)点击运行

5)结果

同时还会自动打开报告(py代码中写的有)

3.8 其他介绍
1)√代表执行成功

2)点击项目名称进去看详情页
如果到时候报错,我们是可以查看我们的控制台的。

3)查看控制台


3.9 Jenkins去集成我们的Allure报告
1)我们要生成对应的报告

2)点击配置

3)找到构建之后操作步骤->allure report

4)勾选之后会有如下页面

5)配置JSON报告所在的地址,细节看图

6)往下翻,找到高级展开,配置html报告的地址

向下找,找到Report path:报告路径,细节🔍如下👇

7)点击保存,再执行一次

执行

8)我们的报告集成成功

报告如下

3.10 Jenkins去集成我们的HTML报告
上面我们说的是让我们Jenkins去集成我们的Allure报告,但是我们如果没有Allure报告的话,我发现只是一个单纯的html报告,那我们如何去集成呢?
还是老规矩跟着我一步一步的去做:
1)回到我们的最初的ant生成html报告的build.xml,如下

2)ok,然后我们要去执行他

3)结果,找到html报告页面

然后找到我们的报告,报告里面有个html报告,我们打开后会看到如下的一个界面

界面如下

他不是我们的Allure报告,他只是一个单纯的html报告,那我们接下来就说Jenkins如何去集成这个html报告。
4)选择配置

5)选择构建HTML报告

6)点击新增

7)配置路径+名字+标题+保存

8)重新运行

9)查看报告
首先点击项目名称查看详细信息

在详情页中选择我们的HTML报告

结果如下

但是你会发现我们的那些样式缺失了,那如何给他找回来呢?继续向下看⬇️
10)修复报告样式
没有样式,我们就装一个groovy就好了,在哪装?如下⬇️
下载 Groovy
从官网下载二进制包:https://groovy.apache.org/download.html

解压

配置环境变量

然后就向上述一样进行插件的配置

让我们重启Jenkins
然后输入这个命令"D:\java\Javajdk\jdk-21\bin\java" -Dhudson.model.DirectoryBrowserSupport.CSP= -jar D:\jenkins.war
通用命令公式
bash
[Java执行路径] -Dhudson.model.DirectoryBrowserSupport.CSP= -jar [Jenkins war包路径]
各部分解释
| 组成部分 | 含义 | 用户需要替换成什么 |
|---|---|---|
[Java执行路径] |
Java 命令的完整路径(如果 java 已加入系统 PATH,可只写 java) |
例如:/usr/bin/java、C:\Program Files\Java\jdk-21\bin\java.exe |
-Dhudson.model.DirectoryBrowserSupport.CSP= |
JVM 参数,用于禁用 Jenkins 的安全策略,让 HTML 报告显示样式。等号后面空着即可 | 固定写法,不需要替换 |
-jar |
Java 命令的参数,表示运行一个可执行的 jar 包 | 固定写法 |
[Jenkins war包路径] |
你下载的 jenkins.war 文件存放的完整路径 |
例如:/home/user/jenkins.war、D:\jenkins.war |
接下来我们要把那些报告全部给删了,重新生成

点击运行

然后我们继续查看我们的html报告

报告结果

3.11 定时自定执行脚本
我们上述执行脚本都是用我们的手动去执行的,那我们可以设置一个定时器,让它自动的去执行我们的脚本。
1)点击配置

2)☑️日程表

3)输入定时时间*表示


那你设置定时器之后,你服务器也不要关闭,如果服务器关闭,他就不会去执行。

OK~~ 那么本期的分享就到此结束啦,干货很多,老铁们看到最后,不要忘了给俺点个免费的赞👍和关注啊,你的关注支持是我继续创作最大的动力
五、写在最后
🎯 看到这里,辛苦啦!歇一歇,喝口水,让眼睛放松一下
这篇笔记我写了很久,如果对你有哪怕一点点帮助,请点一下「关注」 。
后面我还会继续分享很多自学干货笔记,都是自己边学边总结的,依然会是零基础能看懂、每一步都截图的那种详细笔记 。
我是学生,没什么能送你的,只能保证每一篇都认真写、不藏私。
我能给的,就是一篇一篇亲手整理的、零基础也能看懂的干货笔记。
你的每一次关注,都是我继续写下去的动力。
谢谢你的时间,我们下一篇笔记见 👇
(如果这篇笔记有写错的地方,也请一定在评论区告诉我,我会第一时间修改)

下一篇见咯,兄弟们~~

