1概述
JMeter作为一个强大的性能测试工具,预置了很多组件和方法,能解决日常测试中大部分的场景,但复杂的场景需通过编写代码来实现。
在做性能测试时,经常需要提取上面请求的内容,JMeter提供了非常多的提取器
但提取器仅限于一些特定规则的使用,无法覆盖一些特殊的场景。
2 问题场景详述
2.1 问题
给财务云的同学做问题解答时,遇到了一个典型的案例。
业务场景路径:
【企业绩效云】→【合并报表】→【报表编报】→【报表编制】
提取报表名称为”资产负债表”元素的ID,作为下一步操作入参。
它的结构是json数组的形式,并且提取的内容19位的数字串,没有key
在JMeter中的显示如下
2.2 常规方法
2.2.1 JSON提取器
之前小编写过一篇文章《JSON提取器》中介绍过提取同一个内容,可以有四种不同的提取写法,但是由于提取的内容是一个纯数组,没有key,根据数组的下标,可以用此表达式:$[7][27]
需要提取的元素中有”资产负债表”,根据这个特点,我们也可以写成:
$[?(@[3] == '资产负债表')][27]
2.2.2 正则表达式
我们可以写正则表达式:[0-9]{15,22}
注:[0-9]表示0到9任意的数字,{15,22},表示15位到22位,如果确定使用的雪花算法做的ID,一般是19位,我们可以直接写成[0-9]{19},提取出来的是一个数组,我们再通过下标可以提取想要的内容。
2.3 常规方法弊端
• JSON提取器用的表达式$[7][27]和$[?(@[3] == '资产负债表')][27],依赖数据结构的固定,表达式需固定提取数组下标$[7][27]或者[3]的内容,如果返回的数据结构变化,该表达式会失效。
• 正则表达式[0-9]{19},能一次性把19位的纯数字都提取出来,返回的是一个数组,需要指定数组下标才能正确提取。如果换一个组织,或者数据发生变化,该表达式失效。
有没有一种方法能解决上述问题了。根据数据的某个属性,比如需要提取的ID和属性” 资产负债表”在同一个节点,我们可以通过”资产负债表”属性且不依赖于”来精准提取ID。
3、解决办法
使用BeanShell脚本。我们可以先用json提取器直接提取rows节点的内容,然后再利用代码提取rows节点下带有”资产负债表”属性子节点的ID。
具体代码:
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
String reslut = null;
//使用jsont提取器,提取rows的内容
String rows=vars.get("rows");
log.info(rows);
//将rows的内容做分解,提取带有"资产负债表"属性元素的id
JSONArray jsonArray = JSONObject.parseArray(rows);
for (int i = 0; i < jsonArray.size(); i++) {
JSONArray jsonArray2 = jsonArray.getJSONArray(i);
for (int j=0;j<jsonArray2.size();j++) {
String name = jsonArray2.getString(j);
if (name != null && name.equals("资产负债表")) {
String data= JSON.toJSONString(jsonArray2);
Pattern pattern = Pattern.compile("\\b(\\d{15,22})\\b"); // 使用正则表达式提取15-22位的纯数字串
Matcher matcher = pattern.matcher(data);
while (matcher.find()) {
String match = matcher.group(1);
reslut=match;
break;
} } } }
log.info(reslut);
日志打印:Rows节点内容
日志显示成功提取ID: 1697845631902551047
优缺点:
案例比较典型,该方法能成功解决,需要提取的内容不带key、不依赖于数据的结构以及动态数据提取的问题,前面常规的方法依赖返回内容的结构,数据和组织变动后,方法失效。找到可靠的属性,通过beanshell脚本灵活处理,做到精准提取。