一、Jmeter简介
Apache JMeter 是Apache组织的开放源代码项目,是一个纯Java桌面应用,用于压力测试和性能测试。它最初被设计用于Web应用测试但后来扩展到其它测试领域。
- Jmeter具备高移植性,可以实现跨平台运行。
- Jmeter可以实现分布式负载。
- Jmeter采用多线程,允许通过多个线程并发取样或通过独立的线程对不同的功能同时取样。
- Jmeter具有较高扩展性。
- 能够对HTTP和FTP服务器等进行接口测试、压力和性能测试, 也可以对任何数据库进行同样的测试(通过JDBC)
- Jmeter接口测试的简单操作包括做http脚本编辑(发get/post请求、cookie设置、header设置、权限认证)、参数化、断言、关联和数据驱动等等。
二、Jmter安装启动
一般开放原代码软件都会有两个版本发布:Source
和 Binary
- Source 是源代码版,需要自己编译成可执行软件。
- Binary 是可执行版,直接可以拿来用的,已经编译好的版本
- 下载后,解压文件到任意目录,避免在有
空格
的路径安装JMeter。 - 环境依赖: java环境,需要自行安装配置好JDK环境变量
安装Binary的步骤如下:
1、安装JDK,必须JDK1.7以上的版本,推荐1.8的版本
2、进入官网:http://jmeter.apache.org/download_jmeter.cgi 下载最新的Jmeter版本,下载后解压到非中文目录,如:D:
3、配置Jmeter的环境变量。
(1) 新增变量:JMETER_HOME:D:apache-jmeter-4.0.
(2) 在CLASSPATH变量的最前面加入如下变量: %JMETER_HOME%libextApacheJMeter_core.jar;%JMETER_HOME%libjorphan.jar;
(3)在PATH变量的最前面加入如下变量:%JMETER_HOME%in;
4、进入D:apache-jmeter-4.0in,双击jmeter.bat,或在dos窗口输入jmeter命令打开jmeter界面,安装成功。
三、Jmeter主要元件介绍
3.1、主要元件介绍
- 测试计划:是使用 JMeter 进行测试的起点,它是其它 JMeter测试元件的容器
- 线程组:代表一定数量的用户,它可以用来模拟用户并发发送请求。实际的请求内容在Sampler中定义,它被线程组包含。
- 配置元件:维护Sampler需要的配置信息,并根据实际的需要修改请求的内容。
- 前置处理器:负责在请求之前工作,常用来修改请求的设置
- 定时器:负责定义请求之间的延迟间隔。
- 取样器(Sampler):是性能测试中向服务器发送请求,记录响应信息、响应时间的最小单元,如:HTTP Request Sampler、FTP Request Sample、TCP Request Sample、JDBC Request Sampler等,每一种不同类型的sampler 可以根据设置的参数向服务器发出不同类型的请求。
- 后置处理器:负责在请求之后工作,常用获取返回的值。
- 断言:用来判断请求响应的结果是否如用户所期望的。
- 监听器:负责收集测试结果,同时确定结果显示的方式。
- 逻辑控制器:可以自定义JMeter发送请求的行为逻辑,它与Sampler结合使用可以模拟复杂的请求序列。
3.2、元件作用域
- 配置元件:影响其作用范围内的所有元件。
- 前置处理器:在其作用范围内的每一个sampler元件之前执行。
- 定时器:在其作用范围内的每一个sampler有效
- 后置处理器:在其作用范围内的每一个sampler元件之后执行。
- 断言:在其作用范围内的对每一个sampler元件执行后的结果进行校验。
- 监听器:在其作用范围内对每一个sampler元件的信息收集并呈现。
- 总结:从各个元件的层次结构判断每个元件的作用域。
3.3、元件执行顺序
配置元件->前置处理器->定时器->取样器->后置处理程序->断言->监听器
注意事项:
1.前置处理器、后置处理器和断言等组件只能对取样器起作用,因此,如果在它们的作用域内没有任何取样器,则不会被执行。
2.如果在同一作用域内有多个同一类型的元件,则这些元件按照它们在测试计划中的上下顺序依次执行。
四、Jmeter接口测试实践
使用Jmeter进行接口测试的基本步骤如下:
- 新建测试计划
- 添加线程组
- 添加配置元件(HTTP信息头管理器、HTTP请求默认值、HTTP Cookie 管理器等)
- Sampler(HTTP请求等)
- 断言
- 监听器(查看结果树、图形结果、聚合报告等)
下面以 http://httpbin.org 为测试对象,进行接口测试实践
4.1、测试计划
打开Jmeter,在菜单左侧出现 “测试计划”。Jmeter中一个脚本既是一个测试计划,测试计划要素如下:
- 脚本中测试计划只能一个
- 测试计划中至少要有一个线程组
- 至少要有一个取样器
- 至少要有一个监听器
4.2、线程组
添加方法:右键点击测试计划->添加->线程(用户)->线程组。
在线程组界面中可以设置以下数据,进行控制线程组:
1、取样器错误后要执行的动作:
-
继续:忽略错误,继续执行
-
启动下一进程循环: 忽略错误,线程当前循环终止,执行下一个循环。
-
停止线程:当前线程停止执行,不影响其他线程正常执行。
-
停止测试:整个测试会在所有当前正在执行的线程执行完毕后停止
-
立即停止测试:整个测试会立即停止执行,当前正在执行的取样器可能会被中断。
这几个配置项控制了“当遇到错误的时候测试的执行策略”是否会继续执行。
2、设置线程数:
-
线程数也就是并发数,每个线程将会完全独立的运行测试计划,互不干扰。多个线程用于模仿对服务器的并发访问
3、设置ramp-up period
-
ramp-up period用于设置启动所有线程所需要的时间。如果选择了10个线程,并且ramp-up period是100秒,那么JMeter将使用100秒使10个线程启动并运行。每个线程将在前一个线程启动后10(100/10)秒后启动。
-
当这个值设置的很小、线程数又设置的很大时,在刚开始执行时会对服务器产生很大的负荷。
4、设置循环次数
-
该项设置线程组在结束前每个线程循环的次数,如果次数设置为1,那么JMeter在停止前只执行测试计划一次
5、same user on each iteration
- 每次迭代使用相同的线程,即线程复用
6、延迟创建线程直到需要
- 如果勾选了此选项,那么线程只会在合适的需要用到的时候创建
7、线程组调度器设置:一般和循环次数永远配合使用
- 持续时间(秒):设置线程组一直循环的持续时间,单位是秒。
- 启动延迟(秒):设置线程启动延时时间,单位是秒。
如果只是用Jmeter做接口测试,主要关注“取样器错误后要执行的动作”的设置。
4.3、添加配置元件
1、HTTP Cookie管理器
添加方法:右键线程组->添加->配置元件->HTTP Cookie管理器。
元件描述:HTTP Cookie管理器可以像浏览器一样存储和发送cookie,如果你要发送一个带cookie的http请求,cookie manager会自动存储该请求的cookies,并且后面如果发送同源站点的http请求时,都可以用这个cookies。
2、HTTP请求默认值
添加方法:右键线程组->添加->配置元件->HTTP请求默认值。
元件描述:HTTP请求默认值是为了方便填写后续内容而设置。主要填写[服务器名称或IP]和[端口号],后续的HTTP请求中就不用每次都填写IP地址和端口号了。
3、HTTP信息头管理器
添加方法:右键线程组->添加->配置元件->HTTP信息头管理器。
元件描述:HTTP信息头管理器可以设定JMeter发送的HTTP请求头所包含的信息。HTTP信息头中包含有”User-Agent"、“Pragma"、”Referer",“Content-Type”等属性。如传递Json格式的参数,需在管理器里面添加参数类型 Content-Type :application/json
4.4、添加HTTP请求
添加方法:右键线程组->添加->取样器->HTTP请求。
元件描述:HTTP请求包括接口请求方法、请求路径和请求参数等。
HTTP请求详解
- 名称:本属性用于标识一个取样器,建议使用一个有意义的名称。
- 注释:对于测试没有任何作用,仅用户记录用户可读的注释信息。
- 服务器名称或IP :HTTP请求发送的目标服务器名称或IP地址。
- 端口号:目标服务器的端口号,默认值为80 。
- 协议:向目标服务器发送HTTP请求时的协议,可以是HTTP或者是HTTPS ,默认值为http 。
- 方法:发送HTTP请求的方法,可用方法包括GET、POST、HEAD、PUT、TRACE、OPTIONS、DELETE等。
- 路径:目标URL路径(不包括服务器地址和端口)
- 内容编码:内容的编码方式,默认值为iso8859
- 自动重定向:如果选中该选项,当发送HTTP请求后得到的响应是302/301时,JMeter 自动重定向到新的页面。
- 使用keep Alive :保持jmeter 和目标服务器之间的活跃状态,默认选中
- 对Post使用multipart/from-data:当发送POST 请求时,使用multipart/from-data方法发送,默认不选中。
- 同请求一起发送参数 : 在请求中发送URL参数,对于带参数的URL ,jmeter提供了一个简单的对参数化的方法。用户可以将URL中所有参数设置在本表中,表中的每一行是一个参数值对(名称1=值1)。
HTTP的参数设置一般分为两种:参数和消息体数据
- 参数:主要以key = value的参数值对,设置
- 消息体数据:以json格式传递参数,如果出现传送报错的情况,可以在HTTP信息头管理器中添加参数类型 Content-Type :application/json
4.5、响应断言
添加方法:右键HTTP请求->添加->断言->响应断言。一般还会有
元件描述:检查接口是否访问成功。如果检查失败的话会提示找不到断言的内容,没提示的话就代表成功了。
Apply to:指断言作用范围,通常发出一个请求只触发一个请求,所以勾选“main sample only”就可以;若发一个请求可以触发多个服务器请求,就有main sample 和sub-sample之分了。
- Main sample and sub-samples:作用于主请求和子请求
- Main sample only:仅仅只作用于主请求
- Sub-samples only:仅仅只作用于子请求
- Jmeter Variable:作用于jmeter变量(输入框内输入jmeter变量名称)
测试字段
- 响应文本(匹配返回的json数据)、响应代码(匹配返回码:如200, 404,500等)
- 响应信息(匹配响应信息如“OK”字样)
- 响应头(匹配响应头)
- 请求头(匹配请求头)
- URL样本(匹配请求的url链接,如果有重定向则包含请求url 和 重定向url)
- 文档(文本)(匹配响应数据的文本形式)
- 忽略状态(一个请求有多个响应断言,第一个响应断言选中此项,当第一个响应断言失败时可以忽略此响应结果,继续进行下一个断言。如果下一个断言成功则还是判定事务是成功的)
- 请求数据(匹配请求数据)
模式匹配规则
- 包括:响应内容包含需要匹配的内容即代表响应成功,支持正则表达式。
- 匹配:响应内容要完全匹配需要匹配的内容即代表响应成功,大小写不敏感,支持正则表达式。
- 字符串:响应内容包含需要匹配的内容才代表响应成功,大小写敏感,不支持正则表达式
- 相等:响应内容要完全等于需要匹配的内容才代表响应成功,大小写敏感,不支持正则表达式
- 否:相当于取反,如果结果为true,勾上否就是false
- 或者:如果不想用AND连接(所有的模式都必须匹配,断言才算成功),用OR选项可以用于将多个断言模式进行OR连接(只要一个模式匹配,断言就是成功的)
测试模式
- 其实就是断言的数据。点击“添加”按钮,输入要断言的数据。
断言结果
- 如果断言成功,则查看结果树为绿色标志,
- 如果断言失败则为红色显示,如下图所示:
4.6、添加聚会报告(测试报告)
添加方法:线程组 ->右键添加 ->监听器 ->聚合报告。
元件描述:聚合报告是一个比较精简的报告元件,可以查看每个接口的性能情况与执行结果。
报告各个参数含义如下:
- 样本:本次场景中一共完成了多少个请求
- 平均值:平均响应时间(单位:ms)
- 中位数:响应时间的中值(单位:ms)
- 90% 百分位:所有请求中90%的响应时间。
- 最小值:最小响应时间(单位:ms)
- 最大值:最大响应时间(单位:ms)
- 异常%:出错率
- 吞吐量:单位时间内成功地传送数据的数量
- 接收KB/sec:响应数据大小
- 发送KB/sec:发送数据大小
- KB/sec:以流量做衡量的吞吐量
五、Jmeter接口测试进阶
5.1、设置变量
在请求过程中,有时我们需要在请求中设置一些变量来测试不同的场景。Jmeter支持以下类型变量:
- 用户自定义变量
- 函数生成变量
- BeanShell变量
- 数据文件变量
5.1.1、用户自定义变量
用户自定义参数有两种方式:
1、添加前置处理器-用户参数
设置步骤: 选中请求——添加——前置处理器——用户参数
设置变量名称为username,值为test;设置变量名称为password,值为123456
2、添加配置元件-用户定义变量
设置步骤: 选中线程组——添加——配置元件——用户定义的变量
5.1.2、BeanShell变量
什么是Bean Shell?官网:http://www.BeanShell.org/
- BeanShell是一种完全符合Java语法规范的脚本语言,并且又拥有自己的一些语法和方法;
- BeanShell是一种松散类型的脚本语言(这点和JS类似);
- BeanShell是用
Java
写成的,一个小型的、免费的、嵌入式的Java源代码解释器,具有对象脚本语言特性,非常精简。 - BeanShell执行标准Java语句和表达式,另外包括一些脚本命令和语法。
Jmeter有哪些Bean Shell?
- 定时器: BeanShell Timer
- 前置处理器:BeanShell PreProcessor
- 采样器: BeanShell Sampler
- 后置处理器:BeanShell PostProcessor
- 断言: BeanShell断言
- 监听器: BeanShell Listener
Bean Shell预处理程序,设置变量名称为bean_user,值为beantest
5.1.3、CSV数据文件变量及参数化
1、CSV数据文件变量是指从外部csv文件读取数据出来作为变量。
设置步骤: 选择线程组——添加——配置元件——CSV数据文件设置
创建csv文件(最好不用用记事本创建,推荐用Nodepad++)文件编码为UTF-8;
文件内容如下:
test,123456
5.1.4、变量的引用
以上变量设置,在请求时引用变量如下所示: 变量引用格式为:${username},如下:
5.1.5、函数生成变量
Jmeter有许多内置的函数,可以生成随机数。
创建步骤:点击菜单Toos选项——函数助手对话框——下拉选择__Random()
函数 函数配置如下:
函数变量的引用:格式时间复制函数字符串即可。
5.1.6、csv参数化
data_user.csv文件内容如下:
test,123456
dev,654321
ops,111111
在之前的csv数据文件设置需要修改配置如下:表示把所有数据读取一遍,且不重复。
最后修改线程组的线程数量,因为数据中有3组数据,所以设置为3.这样执行就可以看到数据参数化了
执行结果:执行了三次,数据依次取文件中的数据
5.2、关联
接口测试过程中经常需要接口之间关联调用,比如获取上一个接口的返回值,作为另一个接口的请求参数,这里需要使用Jmeter的后置处理器,通过对响应的数据来提取指定的数据。常用的有正则表达式提取器、json提取器、以及BeanShell 后置处理程序
5.2.1、正则表达式提取器
下面是正则表达式各参数值的含义:
- Apply to:
- Main sample and sub-samples:作用于主节点的取样器及对应子节点的取样器
- Main sample only:仅作用于主节点的取样器
- Sub-samples only:仅作用于子节点的取样器
- JMeter Variable:作用于jmeter变量(输入框内可输入jmeter的变量名称),从指定变量值中提取需要的值。
- 引用名称:在HTTP等请求中,引用此数据,需要用到的名称
- 正则表达式:用于将需要的数据提取出来
- 模板:$ 1$ 这是固定格式
- 匹配数值:0代表随机取值,1代表第一值,n代表第n个值
- 缺省值:如果正则表达式没有搜到值,则使用此缺省值
正则正则表达式的格式:字符串形式"token":"(.+?)" 数字形式 “taken”:[(0-9)+]
- ( ) 标记一个子表达式的开始和结束位置。子表达式可以获取供以后使用。要匹配这些字符,请使用 ( 和 )。
- 匹配前面的子表达式一次或多次。要匹配 + 字符,请使用 +。
- . 匹配除换行符 之外的任何单字符。要匹配 . ,请使用 . 。
- ? 匹配前面的子表达式零次或一次,或指明一个非贪婪限定符。要匹配 ? 字符,请使用?。
5.2.2、json提取器
下面是正则表达式各参数值的含义:
- Apply to:
与正在表达式提取器中用法相同,不再赘述。
- Names of created variables:
将JSONPath提取的内容保存到指定变量,多个变量之间用“;”分隔(注意不是用,号)。
- JSON Path expressions:
用于提取响应数据的JSONPath表达式,
多个JSONPath表达式之间用“;”分隔(注意不是用,号)。
- Match No.(0 for Random):
若JSONPath有多个匹配项,可以选择提取哪个匹配项。
0表示随机(默认值),
-1表示提取所有匹配项,各匹配项可用var_1,var_2,var_3,... ,var_n表示(var为保存提取内容的变量名)
i(i=1,2,3,...)表示第i个匹配项,若i大于匹配总数,在设置了缺省值的情况下返回缺省值,否则返回空。
- Compute concatenation var (suffix _ALL):
勾选此选项,若JSONPath返回多个匹配项,
则将各匹配项连接起来保存在var_ALL的变量中,其中var为保存提取内容的变量名。
- Default Values:
若JSONPath没有返回任何结果,则显示设置的缺省值。
注意缺省值可以不设置,一旦设置,需要为每个变量设置缺省值,
多个缺省值之间用“;”分隔(注意不是用,号);多个变量缺省值必须设置。
例子:
- 获取第一层中的某个value值:输入$.url
- 获取第二层List中某个key的value值:使用如下语句:$.json[0].username
- 获取第三层的某个value值:语句为$.json[1].approver[0]
- 获取列表下全部的某一个元素:如下语句$.result[*].name
- 提取特定条件的某个值:写法?(@.object_id==0)为固定写法,常用于列表内元素的筛选,如果值为字符串,则记得加双引号;
- 获取前N个值:则使用语法$.result.records[:2].id
- 获取固定条件下的多个key的value值P:语法$.result.records[?(@.object_id==0)].["id","name","is_active"]
5.2.3、BeanShell 后置处理程序
我们也可以通过Bean Shell获取请求的响应结果,然后设置Jmeter变量,以便后续请求使用,大致步骤:获取请求结果--解析数据--赋值
Bean Shell 常用属性
1.log 打印日志,写入信息到jmeber.log文件。 2.SampleResult 获取SampleResult对象,能通过这个对象获取想要的信息。 3.Response 获取Response对象,能通过这个对象获取响应信息。 4.Failure 查看接口调使用能否成功,假如返回false是成功的,true是失败的。 5.FailureMessage 失败信息,没有设置的时候失败信息是空的,能set这个信息。 6.ResponseData 获取response body类型是byte[]。 7.ResponseCode 返回接口code成功是200。 8.ResponseMessage 获取msg成功是OK。 9.ResponseHeaders 获取接口服务端返回的头部信息。 10.RequestHeaders 获取用户端请求的头部信息。 11.SampleLabel 获取接口请求的名称。 12.SamplerData 获取请求的url和body。 13.ctx 代表上下文信息,能直接用。 14.vars即JMeterVariables,操作jmeter变量,这个变量实际引用了JMeter线程中的局部变量容器(本质上是Map),常用方法: a) vars.get(String key):从jmeter中获得变量值; b) vars.put(String key,String value):数据存到jmeter变量中; 15.prev 获取前面的sample返回的信息,常用方法: a) getResponseDataAsString():获取响应信息。 b) getResponseCode() :获取响应code。
实例:
////导入Json jar包 import com.alibaba.fastjson.JSONObject; //获取返回数据 String returnData = prev.getResponseDataAsString(); //数据转化为json格式 JSONObject jsonObject = JSONObject.parseObject(returnData); JSONObject data = jsonObject.getJSONObject("data"); //data.get返回的是对象,这需要用toString()转化下格式 String username = data.get("username").toString(); String password = data.get("password").toString(); //赋值给username1 vars.put("username1",username); vars.put("password1",password);
5.3、用例数据分离
之前我们的用例数据都是配置在Jmeter Http请求中,每次需要增加,修改用例都需要打开jmeter重新编辑,当用例越来越多的时候,用例维护起来就越来越麻烦,我们可以将用例的数据存放在csv
文件中,然后通过csv文件配置来读取用例中的数据,执行测试。用例数据如下图所示:
用例设计
这里以httpbin接口为例,创建用例文件:testcase.csv
用例名称变量含义:
${caseSeq}
:用例编号${apiType}
:api类型${apiName}
:api名称${priority}
:优先级${url}
:api路径${methods}
:请求方法${parameter}
: 请求参数${expectValue}
:期望值,用于断言
Jmeter设置步骤:
1.新建一个线程组,命名为:Test_Case
2.创建一个http请求默认值,设置如下:
3.添加一个循环控制器
步骤为:线程组——添加——逻辑控制器——循环控制器。
循环控制器的作用可以控制整个用例循环执行的次数。默认值是1
根据用例数量可以修改为4
4.在循环控制器节点下创建CSV文件设置,具体配置内容如下:注意忽略首行
5.创建一个if控制器,步骤为:循环控制器——添加——逻辑控制器——if控制器
if控制器的作用为根据不同条件执行不同的用例,例如这里根据不同的接口请求类型,分别创建了GET
和POST
两个控制器。
条件语句为:"${methods}"=="GET"
其中 ${methods}
表示引用csv中的methods
中的值。
参数:
- Interpret Condition as Variable Expression?:如果这个选项被选中,将不会使用js解析;条件表达式的值必须是
true
(忽略大小写),这里我们取消勾选状态。 - Evaluate for all children:如果选中这一项,在每个子结点执行前都会计算表达式
GET
设置的条件语句如下:
POST
条件语句设置为:"${methods}"=="POST"
6.根据不同请求类型创建用例,如下:
GET请求用例:
GET断言:
POST请求用例, 断言和get请求一样。:
7.最后在线程组添加一个查看结果树,执行可以查看全部用例执行情况。
通过这样的数据驱动,当面对大量用例时在jmeter设置就非常方便,后续的用例维护也非常高效,因为不用在jmeter一个个去单独修改用例了。
5.4、HTML测试报告
有时候我们需要将测试报告以HTML附件形式发送给各个项目成员,那么需要生成HTML报告。 JMeter3.0以后引入了Dashboard Report
,用于生成HTML页面格式图形化报告的扩展模块。执行如下命令(提取设置好环境变量):
jmeter -n -t httpbin_test.jmx -l httpbin.jtl -e -o C: eport
命令的参数:
- -n :以非GUI形式运行Jmeter
- -t :jmeter脚本路径
- -l :result.jtl 运行结果保存路径(.jtl)此文件必须不存在。
- -e :在脚本运行结束后生成html报告
- -o :用于存放html报告的目录,不加该参数默认生成到
bin eport-output