Jmeter的Beanshell断言使用
-
jmeter如何将英文切换为中文${jmeter_home}/bin- 修改
jmeter.properties- 新增一条记录:
language=zh_CN- 注意:如果文件中已经存在
language这个key,且该key处于放开的状态,那么需要在此上进行value的替换
- 注意:如果文件中已经存在
- 新增一条记录:
- 修改
-
jmeter中beanshell的log日志如何看?${jmeter_home}/bin下的jmeter.log- 通过
tail命令就可以看到了beanshell中输出的日志
- 通过
-
解决痛点
jmeter没有怎么使用过的人beanshell刚刚开始入门的同学- 大多数文章处于断章取义吧,只给到部分截图,导致学习的人理解的不是很清晰;
实例场景如下
-
GET请求:http://localhost:9200/_cat/health?format=json-
看下最终的返回数据:
[ { "epoch" : "1648050037", "timestamp" : "15:40:37", "cluster" : "elasticsearch", "status" : "yellow", "node.total" : "1", "node.data" : "11", "shards" : "143", "pri" : "143", "relo" : "0", "init" : "0", "unassign" : "2", "pending_tasks" : "0", "max_task_wait_time" : "-", "active_shards_percent" : "98.6%" } ]
-
-
需求是这样的:
- 场景一
- 通过
Jmeter进行结果断言获取数组的大小,当size==1,证明该请求正确;
- 通过
- 场景二
- 通过
json path进行断言结果判断,当node.total==1,证明该请求正确
- 通过
- 场景一
场景一
-
创建一个事件,如下图所示;
-
将
json相关的包放到${jmeter_home}/lib目录下面,同时避免jmeter没有扫描到我们已经放置好的包,做到如下的配置,可最大避免找到问题的错误;-
图一:当指定的包引入
${jmeter_home}/lib目录下面,我们以fastjson和json为例子,如图: -
为了避免
jmeter没有扫描到指定的包,同时我们创建的事件下引入lib目录,如图:
-
-
创建一个线程组,这里就不做演示了
-
我们创建一个请求,由于该请求带有验证,所以我们会通过如下步骤创建两个小的事件
-
添加一个请求,如图所示
-
添加一个
http的认证,如图所示
-
-
在
http请求目录下,分别添加,截图如下-
BeanShell断言,截图如下:-
由于接下来有两组测试
-
判断结果
size==1,脚本如下import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; String response = prev.getResponseDataAsString(); JSONArray objects = JSON.parseArray(response); int length = objects.size(); log.info("msg value:{}", length); if (length == 1) { Failure = false; FailureMessage = "交易成功!"; } else { Failure = true; FailureMessage = "交易失败!"; } -
判断结果
size==0,脚本如下import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; String response = prev.getResponseDataAsString(); JSONArray objects = JSON.parseArray(response); int length = objects.size(); log.info("msg value:{}", length); if (length == 0) { Failure = false; FailureMessage = "交易成功!"; } else { Failure = true; FailureMessage = "交易失败!"; }
-
-
-
察看结果树
-
-
以上,完成了整个配置,可以看下最终结果,两组测试,分别会是一红一绿
-
判断结果
size==1:绿色,上图 -
判断结果
size==0:红色,上图
-
-
以上是整个
fastjson的beanshell断言的实现
场景二
这里我们使用json-path来进行断言实现,这里采用的json-path的maven如下
<!-- https://mvnrepository.com/artifact/com.jayway.jsonpath/json-path -->
<dependency>
<groupId>com.jayway.jsonpath</groupId>
<artifactId>json-path</artifactId>
<version>2.7.0</version>
</dependency>
-
这里说明一下,和[场景一](# 场景一)唯一的区别就在于第
5步,所以这里我们只做对第5步骤的演示 -
重点:这里必须引入
json-path包,放置在jmeter下面,另外jmeter不支持直接引用·json-path的静态方法,所以只能绕弯路了,如果有人知道,也可以告诉我怎么在beanshell中引入-
这里必须去实现一个
class文件,小弟能力有限,不晓得怎么引入.java文件,索引只能用反编译之后的class文件了import com.jayway.jsonpath.JsonPath; import com.jayway.jsonpath.internal.ParseContextImpl; public class JsonUtil { //public static void main(String[] args) { // String response = "[\n" // + " {\n" // + " \"epoch\" : \"1648050037\",\n" // + " \"timestamp\" : \"15:40:37\",\n" // + " \"cluster\" : \"elasticsearch\",\n" // + " \"status\" : \"yellow\",\n" // + " \"node.total\" : \"1\",\n" // + " \"node.data\" : \"11\",\n" // + " \"shards\" : \"143\",\n" // + " \"pri\" : \"143\",\n" // + " \"relo\" : \"0\",\n" // + " \"init\" : \"0\",\n" // + " \"unassign\" : \"2\",\n" // + " \"pending_tasks\" : \"0\",\n" // + " \"max_task_wait_time\" : \"-\",\n" // + " \"active_shards_percent\" : \"98.6%\"\n" // + " }\n" // + "]"; // // ParseContextImpl parseContext = new ParseContextImpl(); // Object read = JsonPath.read(response, "$.*.cluster"); // //Object read1 = parseContext.parse(read).read("[0]"); // //boolean elasticsearch = Objects.equals(read1, "elasticsearch"); // //System.out.println(elasticsearch); // JsonUtil jsonUtil = new JsonUtil(); // String data = jsonUtil.getData(response, "$.*.cluster"); // String data1 = jsonUtil.getData(data, "[0]"); // boolean elasticsearch = jsonUtil.equals(data1, "elasticsearch"); // System.out.println(elasticsearch); // // //} public String getData(String json, String jsonPath) { Object read = JsonPath.read(json, jsonPath); return read == null ? "" : read.toString(); } public boolean equals(Object obj1, Object obj2) { return obj1.equals(obj2); } } -
beanshell断言脚本如下:#我把JsonUtil.class放在D盘下面 addClassPath("D:\\"); import JsonUtil; String response = prev.getResponseDataAsString(); log.info("msg value:{}", response); JsonUtil jsonUtil = new JsonUtil(); String data = jsonUtil.getData(response, "$.*.cluster"); String data1 = jsonUtil.getData(data,"[0]"); boolean elasticsearch = jsonUtil.equals(data1, "elasticsearch"); log.info("value:{}",elasticsearch); if (elasticsearch) { Failure = false; FailureMessage = "交易成功!"; } else { Failure = true; FailureMessage = "交易失败!"; }
-
这里执行结果就能发现结果是对的
最后附上
jmx内容,希望有人可以用到<?xml version="1.0" encoding="UTF-8"?> <jmeterTestPlan version="1.2" properties="5.0" jmeter="5.4.3"> <hashTree> <TestPlan guiclass="TestPlanGui" testclass="TestPlan" testname="事件一(一级目录)" enabled="true"> <stringProp name="TestPlan.comments">测试fastjson解析 最终结果判断 size==1 为正确</stringProp> <boolProp name="TestPlan.functional_mode">false</boolProp> <boolProp name="TestPlan.tearDown_on_shutdown">true</boolProp> <boolProp name="TestPlan.serialize_threadgroups">false</boolProp> <elementProp name="TestPlan.user_defined_variables" elementType="Arguments" guiclass="ArgumentsPanel" testclass="Arguments" testname="用户定义的变量" enabled="true"> <collectionProp name="Arguments.arguments"/> </elementProp> <stringProp name="TestPlan.user_define_classpath">D:\software\apache-jmeter-5.4.3\lib,D:\software\apache-jmeter-5.4.3\lib\ext\JsonPath.jar</stringProp> </TestPlan> <hashTree> <SetupThreadGroup guiclass="SetupThreadGroupGui" testclass="SetupThreadGroup" testname="线程组(二级目录)" enabled="true"> <stringProp name="ThreadGroup.on_sample_error">continue</stringProp> <elementProp name="ThreadGroup.main_controller" elementType="LoopController" guiclass="LoopControlPanel" testclass="LoopController" testname="循环控制器" enabled="true"> <boolProp name="LoopController.continue_forever">false</boolProp> <stringProp name="LoopController.loops">1</stringProp> </elementProp> <stringProp name="ThreadGroup.num_threads">1</stringProp> <stringProp name="ThreadGroup.ramp_time">1</stringProp> <boolProp name="ThreadGroup.scheduler">false</boolProp> <stringProp name="ThreadGroup.duration"></stringProp> <stringProp name="ThreadGroup.delay"></stringProp> <boolProp name="ThreadGroup.same_user_on_next_iteration">true</boolProp> </SetupThreadGroup> <hashTree> <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="请求(3级目录)" enabled="true"> <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="用户定义的变量" enabled="true"> <collectionProp name="Arguments.arguments"/> </elementProp> <stringProp name="HTTPSampler.domain">locahost</stringProp> <stringProp name="HTTPSampler.port">9200</stringProp> <stringProp name="HTTPSampler.protocol"></stringProp> <stringProp name="HTTPSampler.contentEncoding"></stringProp> <stringProp name="HTTPSampler.path">_cat/health?format=json</stringProp> <stringProp name="HTTPSampler.method">GET</stringProp> <boolProp name="HTTPSampler.follow_redirects">true</boolProp> <boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.use_keepalive">true</boolProp> <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"></stringProp> <stringProp name="HTTPSampler.connect_timeout"></stringProp> <stringProp name="HTTPSampler.response_timeout"></stringProp> </HTTPSamplerProxy> <hashTree> <BeanShellAssertion guiclass="BeanShellAssertionGui" testclass="BeanShellAssertion" testname="BeanShell断言(四级目录)" enabled="true"> <stringProp name="BeanShellAssertion.query">import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; String response = prev.getResponseDataAsString(); JSONArray objects = JSON.parseArray(response); int length = objects.size(); log.info("msg value:{}", length); if (length == 1) { Failure = false; FailureMessage = "交易成功!"; } else { Failure = true; FailureMessage = "交易失败!"; }</stringProp> <stringProp name="BeanShellAssertion.filename"></stringProp> <stringProp name="BeanShellAssertion.parameters"></stringProp> <boolProp name="BeanShellAssertion.resetInterpreter">false</boolProp> </BeanShellAssertion> <hashTree/> <ResultCollector guiclass="ViewResultsFullVisualizer" testclass="ResultCollector" testname="察看结果树(四级目录)" enabled="true"> <boolProp name="ResultCollector.error_logging">false</boolProp> <objProp> <name>saveConfig</name> <value class="SampleSaveConfiguration"> <time>true</time> <latency>true</latency> <timestamp>true</timestamp> <success>true</success> <label>true</label> <code>true</code> <message>true</message> <threadName>true</threadName> <dataType>true</dataType> <encoding>false</encoding> <assertions>true</assertions> <subresults>true</subresults> <responseData>false</responseData> <samplerData>false</samplerData> <xml>false</xml> <fieldNames>true</fieldNames> <responseHeaders>false</responseHeaders> <requestHeaders>false</requestHeaders> <responseDataOnError>false</responseDataOnError> <saveAssertionResultsFailureMessage>true</saveAssertionResultsFailureMessage> <assertionsResultsToSave>0</assertionsResultsToSave> <bytes>true</bytes> <sentBytes>true</sentBytes> <url>true</url> <threadCounts>true</threadCounts> <idleTime>true</idleTime> <connectTime>true</connectTime> </value> </objProp> <stringProp name="filename"></stringProp> </ResultCollector> <hashTree/> </hashTree> <AuthManager guiclass="AuthPanel" testclass="AuthManager" testname="HTTP授权管理器(3级目录)" enabled="true"> <collectionProp name="AuthManager.auth_list"> <elementProp name="" elementType="Authorization"> <stringProp name="Authorization.url"></stringProp> <stringProp name="Authorization.username">1111</stringProp> <stringProp name="Authorization.password">111</stringProp> <stringProp name="Authorization.domain"></stringProp> <stringProp name="Authorization.realm"></stringProp> </elementProp> </collectionProp> <boolProp name="AuthManager.controlledByThreadGroup">false</boolProp> </AuthManager> <hashTree/> </hashTree> <SetupThreadGroup guiclass="SetupThreadGroupGui" testclass="SetupThreadGroup" testname="线程组(二级目录)" enabled="true"> <stringProp name="TestPlan.comments">json-path使用</stringProp> <stringProp name="ThreadGroup.on_sample_error">continue</stringProp> <elementProp name="ThreadGroup.main_controller" elementType="LoopController" guiclass="LoopControlPanel" testclass="LoopController" testname="循环控制器" enabled="true"> <boolProp name="LoopController.continue_forever">false</boolProp> <stringProp name="LoopController.loops">1</stringProp> </elementProp> <stringProp name="ThreadGroup.num_threads">1</stringProp> <stringProp name="ThreadGroup.ramp_time">1</stringProp> <boolProp name="ThreadGroup.scheduler">false</boolProp> <stringProp name="ThreadGroup.duration"></stringProp> <stringProp name="ThreadGroup.delay"></stringProp> <boolProp name="ThreadGroup.same_user_on_next_iteration">true</boolProp> </SetupThreadGroup> <hashTree> <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="请求(3级目录)" enabled="true"> <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="用户定义的变量" enabled="true"> <collectionProp name="Arguments.arguments"/> </elementProp> <stringProp name="HTTPSampler.domain">ip</stringProp> <stringProp name="HTTPSampler.port">9200</stringProp> <stringProp name="HTTPSampler.protocol"></stringProp> <stringProp name="HTTPSampler.contentEncoding"></stringProp> <stringProp name="HTTPSampler.path">_cat/health?format=json</stringProp> <stringProp name="HTTPSampler.method">GET</stringProp> <boolProp name="HTTPSampler.follow_redirects">true</boolProp> <boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.use_keepalive">true</boolProp> <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> <stringProp name="HTTPSampler.embedded_url_re"></stringProp> <stringProp name="HTTPSampler.connect_timeout"></stringProp> <stringProp name="HTTPSampler.response_timeout"></stringProp> </HTTPSamplerProxy> <hashTree> <ResultCollector guiclass="ViewResultsFullVisualizer" testclass="ResultCollector" testname="察看结果树(四级目录)" enabled="true"> <boolProp name="ResultCollector.error_logging">false</boolProp> <objProp> <name>saveConfig</name> <value class="SampleSaveConfiguration"> <time>true</time> <latency>true</latency> <timestamp>true</timestamp> <success>true</success> <label>true</label> <code>true</code> <message>true</message> <threadName>true</threadName> <dataType>true</dataType> <encoding>false</encoding> <assertions>true</assertions> <subresults>true</subresults> <responseData>false</responseData> <samplerData>false</samplerData> <xml>false</xml> <fieldNames>true</fieldNames> <responseHeaders>false</responseHeaders> <requestHeaders>false</requestHeaders> <responseDataOnError>false</responseDataOnError> <saveAssertionResultsFailureMessage>true</saveAssertionResultsFailureMessage> <assertionsResultsToSave>0</assertionsResultsToSave> <bytes>true</bytes> <sentBytes>true</sentBytes> <url>true</url> <threadCounts>true</threadCounts> <idleTime>true</idleTime> <connectTime>true</connectTime> </value> </objProp> <stringProp name="filename"></stringProp> </ResultCollector> <hashTree/> <BeanShellAssertion guiclass="BeanShellAssertionGui" testclass="BeanShellAssertion" testname="BeanShell断言(四级目录)" enabled="true"> <stringProp name="BeanShellAssertion.query">addClassPath("D:\\"); import JsonUtil; String response = prev.getResponseDataAsString(); log.info("msg value:{}", response); JsonUtil jsonUtil = new JsonUtil(); String data = jsonUtil.getData(response, "$.*.cluster"); String data1 = jsonUtil.getData(data,"[0]"); boolean elasticsearch = jsonUtil.equals(data1, "elasticsearch"); log.info("value:{}",elasticsearch); if (elasticsearch) { Failure = false; FailureMessage = "交易成功!"; } else { Failure = true; FailureMessage = "交易失败!"; }</stringProp> <stringProp name="BeanShellAssertion.filename"></stringProp> <stringProp name="BeanShellAssertion.parameters"></stringProp> <boolProp name="BeanShellAssertion.resetInterpreter">false</boolProp> </BeanShellAssertion> <hashTree/> </hashTree> <AuthManager guiclass="AuthPanel" testclass="AuthManager" testname="HTTP授权管理器(3级目录)" enabled="true"> <collectionProp name="AuthManager.auth_list"> <elementProp name="" elementType="Authorization"> <stringProp name="Authorization.url"></stringProp> <stringProp name="Authorization.username">1111</stringProp> <stringProp name="Authorization.password">1111</stringProp> <stringProp name="Authorization.domain"></stringProp> <stringProp name="Authorization.realm"></stringProp> </elementProp> </collectionProp> <boolProp name="AuthManager.controlledByThreadGroup">false</boolProp> </AuthManager> <hashTree/> </hashTree> </hashTree> </hashTree> </jmeterTestPlan> -