►►►
简介
1、概述-
Apache JMeter 是 Apache 基于 Java 开发的开源压力测试工具
-
最初被设计用于 Web 应用测试,但后来扩展到了其他测试领域,像接口测试
-
但,随着 IT 行业的快速发展,不同企业或组织需求更加丰富,JMeter 默认的功能往往不能满足所有的需求,在一些企业里,会对这款工具进行二次开发
-
JDK:Java 开发工具包,是所有 Java 开发或项目运行的基础
-
IntelliJ IDEA:一个进行 Java 项目开发的集成开发环境,也可以使用 Eclipse
-
JMeter:下载最新版本即可,但插件开发时的依赖版本与使用的 JMeter 版本保持 一致
►►►
函数开发
1、概述JMeter 自带函数库中,提供了丰富的函数,并被广泛使用,如__Random、__UUID 等
可以通过菜单工具-> 函数助手对话框进行测试,如下图
但,不同接口测试、性能测试项目或场景中,有着不同的特性,JMeter 自带的函数并不完全满足业务需要。
基于 JMeter 的自定义函数开发,就能满足各类特性业务的需求,在实际的测试中有着非常重要的应用
►►►
自定义函数
1、核心 API自定义函数必须继承 AbstractFunction 类,并重写父类的 4 个方法
-
execute,函数执行逻辑,必需,自定义函数的核心逻辑,并返回经过处理后的内
-
getReferenceKey,函数名称,必需,返回一个字符串,表示在 JMeter 中使用自定义函数的函数名,一般以双下划线开头,如__Operate、__IDNumber
-
setParameters,设置函数接收参数值,如果自定义函数有参数,用于接收调用时传递过来的参数,注意使用时,字符串参数不要加双引号
-
getArgumentDesc,函数参数描述,如果自定义函数有参数,用于返回函数参数说明
►►►
开发步骤
-
创建 Maven 项目:使用 IDEA 创建一个 Maven 项目
-
添加依赖:在项目的 pom.xml 中依赖 ApacheJMeter_java、ApacheJMeter_core,注意与使用的 JMeter 版本保持一致,依赖见附件
-
自定义函数:
添加自定义函数,继承 AbstractFunction 类,并覆写其 4 个方法
execute 方法:添加插件逻辑
getReferenceKey 方法:返回自定义名称函数,用于在 JMeter 中调用
setParameters 方法:获取传递的参数
getArgumentDesc:返回参数描述
注意,自定义函数必须在*.functions 包下 -
打包:使用 Maven 工具将插件打包成。jar 文件,在项目下的 target 目录中
-
发布:将打包的。jar 文件拷贝到 JMeter 安装目录的 lib/ext 目录中
-
重启 JMeter:重新启动 JMeter,此时就可以 JMeter 中使用。jar 包中自定义的函数
►►►
示例一:开发一个简单的运算函数
-
函数名:__Operate
-
参数:分别为运算符、操作数 1、操作数 2
-
代码:
package com.lemon.demo.jmeter.functions;import org.apache.jmeter.engine.util.CompoundVariable;import org.apache.jmeter.functions.AbstractFunction;import org.apache.jmeter.functions.InvalidVariableException;import org.apache.jmeter.samplers.SampleResult;import org.apache.jmeter.samplers.Sampler;import org.apache.jmeter.util.JMeterUtils;import java.util.Collection;import java.util.LinkedList;import java.util.List;public class Operate extends AbstractFunction { //操作符 private String operate; //操作数1 private Double first; //操作数2 private Double second; @Override public String execute(SampleResult previousResult, Sampler currentSampler) { Double result = 0d; //算术运算 if ("+".equals(this.operate)) { result = this.first + this.second; }else if ("-".equals(this.operate)) { result = this.first - this.second; }else if ("*".equals(this.operate)) { result = this.first * this.second; }else if ("/".equals(this.operate)) { result = this.first / this.second; } return result.toString(); } @Override public void setParameters(Collection parameters) throws InvalidVariableException { //检查参数个数 checkParameterCount(parameters,3,3); //获取参数 Object[] params = parameters.toArray(); //获取运算符 CompoundVariable cvOperate = (CompoundVariable) params[0]; this.operate = cvOperate.execute(); //获取操作数1 CompoundVariable cvFirst = (CompoundVariable) params[1]; this.first = Double.parseDouble(cvFirst.execute()); //获取操作数2 CompoundVariable cvSecond = (CompoundVariable) params[2]; this.second = Double.parseDouble(cvSecond.execute()); } @Override public String getReferenceKey() { return "__Operate"; } @Override public List getArgumentDesc() { List desc = new LinkedList(); desc.add("运算符"); desc.add("操作数1"); desc.add("操作数2"); return desc; }}
►►►
示例二:动态生成身份证号码函数
需求:需要一个根据区域动态生成合格的身份证号码的公共函数
函数名:__IDNumber(区域名称),如__IDNumber(长沙市),将返回一个长沙的随机身份证号码
参数:区域
代码:
package com.lemon.demo.jmeter.functions;import com.lemon.demo.util.IdNumberGenerateUtil;import lombok.extern.slf4j.Slf4j;import org.apache.jmeter.engine.util.CompoundVariable;import org.apache.jmeter.functions.AbstractFunction;import org.apache.jmeter.functions.InvalidVariableException;import org.apache.jmeter.samplers.SampleResult;import org.apache.jmeter.samplers.Sampler;import java.util.ArrayList;import java.util.Collection;import java.util.LinkedList;import java.util.List;@Slf4jpublic class IDNumber extends AbstractFunction { //参数 private String area; public String execute(SampleResult sampleResult, Sampler sampler) { //调用身份证生成逻辑 String idNumber = IdNumberGenerateUtil.generate(area); return idNumber; } public void setParameters(Collection parameters) throws InvalidVariableException { //检查参数个数 checkParameterCount(parameters,0,1); //获取参数 Object[] params = parameters.toArray(); //获取区域 if(params.length>0) { CompoundVariable cvArea = (CompoundVariable) params[0]; this.area = cvArea.execute(); } } public String getReferenceKey() { return "__IDNumber"; } public List getArgumentDesc() { List desc = new ArrayList(); desc.add("Area"); return desc; }}
►►►
JMeter 二次开发方向
-
函数开发,丰富 JMeter 通用的函数库,加速用例设计中的通用功能开发,如加密/解密、签名生成、随机生成身份证号码等
-
插件开发,丰富 JMeter 的测试应用场景,有效提升软件产品测试效能,一般主要做取样器开发,如接口自由协议、Java 服务请求等
-
基于执行引擎开发,有效解决单独开发的测试平台或工具中,底层执行引擎开发相对复杂、周期长的问题,利用 JMeter 执行引擎的 API 进行基础的调用、监听、提取等操作,加速底层执行引擎开发效率;同时,又能弥补 JMeter 本身做为一个工具的一些缺点,如界面相对复杂、报表少且图形化效果差、不能对测试过程进行审计管理等
-
完全基于 JMeter 源码开发,JMeter 本身产品结构、执行流程相对稳定,并且代码量大,逻辑也相对复杂,直接对源码进行二次开发投入时间长,收益低,一般不这么做;但参考其代码有利于插件开发
技能提升 -
最后感谢每一个认真阅读我文章的人,看着粉丝一路的上涨和关注,礼尚往来总是要有的,虽然不是什么很值钱的东西,如果你用得到的话可以直接拿走
这些资料,对于做【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴我走过了最艰难的路程,希望也能帮助到你!凡事要趁早,特别是技术行业,一定要提升技术功底。希望对大家有所帮助…….



