使用命令行方式运行Jmeter

前言

命令行方式支持在多个环境下使用,windosw的dos环境下,也可以在linux环境上执行。

怎么用

执行路径:执行命令前要检查当前目录是否是%JMeter_Home%\bin目录;如果 JMeter 脚本不在当前目录,需要指定完整的路径;如果要把执行的结果保存在其他地方也要指定完整的路径。命令中不指定测试计划与测试结果的路径时,默认都是在该目录下。

命令:jmeter -n -t <testplan filename> -l <listener filename>

示例

测试计划与结果,都在%JMeter_Home%\bin目录

1
jmeter -n -t test1.jmx -l result.jtl 

指定日志路径的

1
jmeter -n -t test1.jmx -l report\01-result.csv -j report\01-log.log

默认分布式执行

1
jmeter -n -t test1.jmx -r -l report\01-result.csv -j report\01-log.log

指定IP分布式执行

1
jmeter -n -t test1.jmx -R 192.168.10.25:1036 -l report\01-result.csv -j report\01-log.log

生成测试报表

1
2
3
# 格式: jmeter -n -t 【Jmx脚本位置】-l 【中间文件result.jtl位置】-e -o 【报告指定文件夹】

jmeter -n -t test1.jmx -l report\01-result.jtl -e -o tableresult

已有jtl结果文件,运行命令生成报告

1
2
3
# 格式: jmeter -g【已经存在的.jtl文件的路径】-o 【用于存放html报告的目录】

jmeter -g result.jtl -o ResultReport

动态设置线程数、rame up等参数

使用非gui的方式执行jmeter,若需更改参数,必须先编辑jmx文件,找到对应的变量进行修改,比较麻烦。因此,可以参数化一些常用的变量,直接在Jmeter命令行进行设置

参数 -J 和 -G

1、格式:-J变量名=值 -G变量名=值

2、相同之处:设置jmeter属性,例如线程数、循环次数、ramp up-time等

3、不同之处:**-J是设置本地jmeter属性;-G是设置server的jmeter属性(只有设置了远程机,开启了远程服务,才需要用到-G)**

以设置本地jmeter属性为例

先在windows下编辑脚本,将线程数、循环次数、ramp up-time等参数化

1、添加用户自定义变量(添加变量的具体方法请参考Jmeter添加变量的四种方法

定义三个变量和变量对应的默认值,例如${__P(threadNum,1)},表示变量threadNum的默认值为1

2、引用用户自定义变量,将线程属性和用户自定义变量关联起来

3、运行脚本,验证变量是否设置成功

两个样本请求的线程数都为1,说明设置成功(自定义变量中,变量的默认值都为1)

保存脚本,执行文件

1)执行命令:jmeter -n -t httptest.jmx -l log_httptest.jtl -JthreadNum=100 -JloopNum=10 -JrampupTime=10

2)将log_httptest.jtl文件传到windows下,查看结果

3)再次运行脚本时,无需编辑脚本,只需要在执行命令中更改threadNum、loopNum和rampupTime的值,即可修改线程属性

注意

1)设置-e -o之前,需要修改jmeter.properties,否则会报错

2)-l 与-o 目录不一样,最后生成两个文件夹下

3)命令中不写位置的话中间文件默认生成在bin下,下次执行不能覆盖,需要先删除result.jtl;报告指定文件夹同理,需要保证文件夹为空

模板为report-template,结果目录%JMeter_Home%\bin\resulttable

结果文件 - 生成报告

结果文件类型为jtlcsv,测试计划里添加的哪种监听器,就可通过JMeter的相应的监听器浏览结果文件,查看最终的结果。

也可以用xslproc,将jtl格式转为html的形式。

xsltproc

xsltproc是由DanielVeillard用来C语言编写的是一个快速XSLT引擎,它可以将通过XSL层叠样式表把XML转换为相应格式的文件,比如:HTML,XHTML,PDF...

xsltproc git地址:https://github.com/behappy-other/xslt

下载安装参考:https://www.crifan.com/files/doc/docbook/docbook_dev_note/release/webhelp/download_xsltproc_win.html

调用jmeter,并生成报告

1
%JMeter_Home%/bin/jmeter.sh -n -t ScriptName.jmx -l log.jtl

jtl格式转换成html格式

1
xsltproc %JMeter_Home%/extras/jmeter-results-detail-report.xsl log.jtl> newlog.html

说明:

jmeter-results-detail-report.xsl 、jmeter-results-report.xsl是文件转换模板,这个都可以进行编辑,比如添加一些值显示。

利用jmeter生成

最终报告样式

参考:

Python 调 Jmeter 执行参数化 jmx 脚本

Jmeter Thread Group中如果存在HTTP request执行失败,就对整个Thread Group重新执行,限定最大执行次数N次

利用xsltproc转换jtl报告到html报告

生成动态报告

JMeter3.0版本发布后,支持动态报表报告。编写性能测试报告更加容易。 这里是对生成报告示例的详细描述。

测试过程:执行测试文件 --》生成测试结果文件 --》生成最终的测试报告

准备

修改jmeter.properties

save这块的内容基本上都改成true就行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
jmeter.save.saveservice.data_type=true
jmeter.save.saveservice.label=true
jmeter.save.saveservice.response_code=true
# response_data is not currently supported for CSV output
jmeter.save.saveservice.response_data=true
# Save ResponseData for failed samples
jmeter.save.saveservice.response_data.on_error=false
jmeter.save.saveservice.response_message=true
jmeter.save.saveservice.successful=true
jmeter.save.saveservice.thread_name=true
jmeter.save.saveservice.time=true
jmeter.save.saveservice.subresults=true
jmeter.save.saveservice.assertions=true
jmeter.save.saveservice.latency=true
jmeter.save.saveservice.connect_time=true
jmeter.save.saveservice.samplerData=true
jmeter.save.saveservice.responseHeaders=true
jmeter.save.saveservice.requestHeaders=true
jmeter.save.saveservice.encoding=false
jmeter.save.saveservice.bytes=true
# Only available with HttpClient4
#jmeter.save.saveservice.sent_bytes=true
jmeter.save.saveservice.url=true
jmeter.save.saveservice.filename=true
jmeter.save.saveservice.hostname=true
jmeter.save.saveservice.thread_counts=true
jmeter.save.saveservice.sample_count=true
jmeter.save.saveservice.idle_time=true
# Timestamp format - this only affects CSV output files
# legitimate values: none, ms, or a format suitable for SimpleDateFormat
jmeter.save.saveservice.timestamp_format=ms
jmeter.save.saveservice.timestamp_format=yyyy/MM/dd HH:mm:ss

jmeter.properties或者user.properties确认如下配置项:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
jmeter.save.saveservice.bytes = true
jmeter.save.saveservice.label = true
jmeter.save.saveservice.latency = true
jmeter.save.saveservice.response_code = true
jmeter.save.saveservice.response_message = true
jmeter.save.saveservice.successful = true
jmeter.save.saveservice.thread_counts = true
jmeter.save.saveservice.thread_name = true
jmeter.save.saveservice.time = true
# the timestamp format must include the time and should include the date.
# For example the default, which is milliseconds since the epoch:
jmeter.save.saveservice.timestamp_format = ms
# Or the following would also be suitable
jmeter.save.saveservice.timestamp_format = yyyy/MM/dd HH:mm:ss

如果希望在Errors报告中展示更详细数据,需要确保如下配置

1
jmeter.save.saveservice.assertion_results_failure_message = true

如果使用了事务控制器(Transaction Controller),确认Generate parent sample为未勾选状态

命令

1
2
3
# 格式:jmeter -n -t 【Jmx脚本位置】-l 【中间文件result.jtl位置】-e -o 【报告指定文件夹】 

# 命令执行测试文件,生成测试结果文件jtl,生成最终的测试报告

报告示例

打开【报告指定文件夹】的index.html页面

报告解释

  • APDEX(Application Performance Index)

应用程序性能满意度的标准,范围在0-1之间,1表示达到所有用户均满意。是由APDEX公司推出的。计算公式:

  • Requests Summary

请求的通过率(OK)与失败率(KO),百分比显示。

  • Statistics

数据分析,基本将Summary Report和Aggrerate Report的结果合并。

  • Errors

错误情况,依据不同的错误类型,将所有错误结果展示。

  • Top 5 Errors by sampler

top5错误

  • Over Time

Response Times Over Time: 响应时间

Bytes Throughput Over Time: 字节接收/发送的数量

Latencies Over Time:延迟时间

  • Throughput

Hits Per Second: 每秒点击率

Codes Per Second: 每秒状态码数量

Transactions Per Second: 每秒事务量

Response Time Vs Request: 响应时间点请求的成功/失败数

Latency Vs Request: 延迟时间点请求的成功/失败数

  • Response Times

Response Time Percentiles: 响应时间百分比

Active Threads Over Time: 激活线程数

Time Vs Threads: 测试过程中的线程数时续图

Response Time Distribution: 响应时间分布

参考

1
2
3
4
5
# bat脚本
del /s /Q D:\apache-jmeter-3.2\bin\result.jtl
rd /s /Q D:\abc\HttpReport
md D:\abc\HttpReport
jmeter -n -t D:\apache-jmeter-3.2\bin\test1.jmx -l result.jtl -e -o D:\abc\HttpReport

del是删除jtlrd是删除报告文件夹,md是重建报告文件夹(可省略),最后执行命令生成报告。

其他

jmeter-results-detail-report.xsl 、jmeter-results-report.xsl是文件转换模板,都可以进行编辑,比如添加一些值显示。

以下修改内容仅针对这两个文件

邮件发送html报告有中文时,显示乱码

修改encoding为“UTF-8”

1
<xsl:output method="html" indent="yes" encoding="UTF-8" doctype-public="-//W3C//DTD HTML 4.01 Transitional//EN" />

Summary中的只标红Failures数

  • 屏蔽Summary中class属性
1
2
3
4
5
6
7
<!-- 			
<xsl:attribute name="class">
<xsl:choose>
<xsl:when test="$allFailureCount &gt; 0">Failure</xsl:when>
</xsl:choose>
</xsl:attribute>
-->
  • 修改allFailureCount
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<td align="center">
<xsl:value-of select="$allSuccessCount" />
</td>
<xsl:choose>
<xsl:when test="$allFailureCount &gt; 0">
<td align="center" style="font-weight:bold">
<font color="red">
<xsl:value-of select="$allFailureCount" />
</font>
</td>
</xsl:when>
<xsl:otherwise>
<td align="center">
<xsl:value-of select="$allFailureCount" />
</td>
</xsl:otherwise>
</xsl:choose>

Pages页面按Average Time倒序排序

在Pagelist模板中for-each下添加

1
2
3
<xsl:for-each select="/testResults/*[not(@lb = preceding::*/@lb)]"	>
<!-- 按平均时间排序 -->
<xsl:sort select="sum(../*[@lb = current()/@lb]/@t) div count(../*[@lb = current()/@lb])" data-type="number" order="descending"/>

接口Average Time超过2s标黄显示

  • 添加LongTime css
1
2
3
4
5
6
7
.Failure {
font-weight:bold; color:red;
}
.LongTime {
font-weight:bold; color:#ff9900;
}

  • Pagelist 模块中针对错误和超长时间接口标色显示
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<tr valign="top">
<xsl:choose>
<!-- 失败用例标红显示 -->
<xsl:when test="$failureCount &gt; 0">
<xsl:attribute name="class">
<xsl:choose>
<xsl:when test="$failureCount &gt; 0">Failure</xsl:when>
</xsl:choose>
</xsl:attribute>
</xsl:when>
<!-- 平均时间超过2s,标色显示 -->
<xsl:when test="$averageTime &gt; 2000">
<xsl:attribute name="class">
<xsl:choose>
<xsl:when test="$averageTime &gt; 2000">LongTime</xsl:when>
</xsl:choose>
</xsl:attribute>
</xsl:when>
</xsl:choose>

添加90% Line和QPS

  • 添加90 %lineTime模板
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
<xsl:template name="max">
<xsl:param name="nodes" select="/.." />
<xsl:choose>
<xsl:when test="not($nodes)">NaN</xsl:when>
<xsl:otherwise>
<xsl:for-each select="$nodes">
<xsl:sort data-type="number" order="descending" />
<xsl:if test="position() = 1">
<xsl:value-of select="number(.)" />
</xsl:if>
</xsl:for-each>
</xsl:otherwise>
</xsl:choose>
</xsl:template>

<!-- 90% line time -->
<xsl:template name="lineTime">
<xsl:param name="nodes" select="/.." />
<xsl:choose>
<xsl:when test="not($nodes)">NaN</xsl:when>
<xsl:otherwise>
<xsl:for-each select="$nodes">
<xsl:sort data-type="number" />
<!-- last() 返回当前上下文中的最后一个节点位置数 -->
<!-- ceiling(number) 返回大于number的最小整数 -->
<!-- floor(number) 返回不大于number的最大整数 -->
<!-- position() 返回当前节点位置的数字 -->
<!-- number(object) 使对象转换成数字 -->
<xsl:choose>
<!-- 当只有一个节点时,向上取整 -->
<xsl:when test="last() = 1">
<xsl:if test="position() = ceiling(last()*0.9)">
<xsl:value-of select="number(.)" />
</xsl:if>
</xsl:when>
<xsl:otherwise>
<xsl:if test="position() = floor(last()*0.9)">
<xsl:value-of select="number(.)" />
</xsl:if>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
  • Sunmary中添加标题
1
2
3
4
5
6
7
8
9
10
11
<tr valign="top">
<th># Samples</th>
<th>Success</th>
<th>Failures</th>
<th>Success Rate</th>
<th>Average Time</th>
<th>Min Time</th>
<th>Max Time</th>
<th>90% Line</th>
<th>QPS</th>
</tr>
  • Summary中添加allLineTime和qps变量
1
2
3
4
5
6
7
8
9
10
11
12
13
<xsl:variable name="allMaxTime">
<xsl:call-template name="max">
<xsl:with-param name="nodes" select="/testResults/*/@t" />
</xsl:call-template>
</xsl:variable>
<!-- New add 90% line -->
<xsl:variable name="allLineTime">
<xsl:call-template name="lineTime">
<xsl:with-param name="nodes" select="/testResults/*/@t" />
</xsl:call-template>
</xsl:variable>
<!-- 将毫秒转换成秒 -->
<xsl:variable name="qps" select="$allCount * 1000 div $allTotalTime"/>
  • Summary中调用allLineTime和qps变量
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<td align="center">
<xsl:call-template name="display-time">
<xsl:with-param name="value" select="$allMaxTime" />
</xsl:call-template>
</td>
<td align="center">
<xsl:call-template name="display-time">
<xsl:with-param name="value" select="$allLineTime" />
</xsl:call-template>
</td>
<td align="center">
<xsl:call-template name="display-qps">
<xsl:with-param name="value" select="$qps" />
</xsl:call-template>
  • pagelist中添加标题
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<xsl:template name="pagelist">
<h2>Pages</h2>
<table align="center" class="details" border="0" cellpadding="5" cellspacing="2" width="95%">
<tr valign="top">
<th>URL</th>
<th># Samples</th>
<th>Success</th>
<th>Failures</th>
<th>Success Rate</th>
<th>Average Time</th>
<th>Min Time</th>
<th>Max Time</th>
<th>90% Line</th>
<th>QPS</th>
<th></th>
</tr>
  • pagelist中添加allLineTime和qps变量
1
2
3
4
5
6
7
8
9
10
11
12
<xsl:variable name="maxTime">
<xsl:call-template name="max">
<xsl:with-param name="nodes" select="../*[@lb = current()/@lb]/@t" />
</xsl:call-template>
</xsl:variable>
<!-- new add 90% line time -->
<xsl:variable name="nintyTime">
<xsl:call-template name="lineTime">
<xsl:with-param name="nodes" select="../*[@lb = current()/@lb]/@t" />
</xsl:call-template>
</xsl:variable>
<xsl:variable name="qpsTime" select="$count * 1000 div $totalTime"/>
  • pagelist中调用allLineTime和qps变量
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<td align="center">
<xsl:call-template name="display-time">
<xsl:with-param name="value" select="$maxTime" />
</xsl:call-template>
</td>
<!-- Page页面添加90% LineTime -->
<td align="center">
<xsl:call-template name="display-time">
<xsl:with-param name="value" select="$nintyTime" />
</xsl:call-template>
</td>
<td align="center">
<xsl:call-template name="display-qps">
<xsl:with-param name="value" select="$qpsTime" />
</xsl:call-template>
</td>

Failure Detail模块显示Response Data

  • 设置showData为‘y’
1
2
3
4
<!-- Defined parameters (overrideable) -->
<xsl:param name="showData" select="'y'"/>
<xsl:param name="titleReport" select="'Interface Test Results'"/>
<xsl:param name="dateReport" select="'date not defined'"/>
  • 替换内容
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<table class="details" border="0" cellpadding="5" cellspacing="2" width="95%">
<tr valign="top">
<th align="center">Response</th>
<th align="center">Failure Message</th>
<xsl:if test="$showData = 'y'">
<th align="left">Response Data</th>
</xsl:if>
</tr>

<xsl:for-each select="/testResults/*[@lb = current()/@lb][attribute::s='false']">
<tr>
<td><xsl:value-of select="@rc | @rs" /> - <xsl:value-of select="@rm" /></td>
<td><xsl:value-of select="assertionResult/failureMessage" /></td>
<xsl:if test="$showData = 'y'">
<td><xsl:value-of select="responseData" /></td>
</xsl:if>
</tr>
</xsl:for-each>

添加Host

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<xsl:template name="pageHeader">
<h1><xsl:value-of select="$titleReport" /></h1>
<table width="100%">
<tr>
<!-- 获取requestHeader数据 -->
<xsl:variable name="req" select="/testResults/httpSample/requestHeader" />
<!-- 从获取的URL中截取数据,以Host:分割,取后半部分 -->
<xsl:variable name="remaining" select="substring-after($req,'Host:')" />
<!-- 已换行符来截取,before代表换行符之前的数据 -->
<xsl:variable name="host" select="substring-before($remaining, '&#xA;')" />
<td align="left">Date report: <xsl:value-of select="$dateReport" /></td>
<td align="center">Host: <xsl:value-of select="$host" /></td>
<td align="right"><a href="./TestLog.html">测试日志</a></td>
</tr>
</table>
<hr size="1" />
</xsl:template>