在项目实践中,遇到了这样一个问题。用jmeter作http接口测试,需要的接口参数个数是不确定的。也就是说,在每次测试中,根据情况不同,可能页面中的列表中所含的参数个数是不确定的,那么要提取的参数个数也是不确定的,可能是1个,也可能是2个或3个,甚至更多。

例如,返回的接口消息json消息可能如下

{
"data": {
"records": [{
"DEVICE_TYPE": 194,
"DEVICE_STATUS": 0,
"ORG_NAME": "**省",
"LONGITUDE": "0.000000",
"DEVICE_NAME": "测试1",
"DEVICE_ADDR": "",
"DEVICE_ID_INT": "13",
"HAVE_VIDEO": "true",
"OWNER": "-1",
"ORIGINAL_DEVICE_ID": "44000000011325******",
"PLATFORM_ID": "44000000052005******",
"ORG_CODE": "44",
"TYPE": "1",
"DEVICE_ID": "44000000011325******",
"LATITUDE": "0.000000"
}, {
"DEVICE_TYPE": 194,
"DEVICE_STATUS": 0,
"LONGITUDE": "0.000000",
"DEVICE_NAME": "测试2",
"DEVICE_ADDR": "",
"DEVICE_ID_INT": "10",
"HAVE_VIDEO": "true",
"OWNER": "1",
"ORIGINAL_DEVICE_ID": "44010000001320******",
"PLATFORM_ID": "44000000052005******",
"ORG_CODE": "4401",
"TYPE": "1",
"DEVICE_ID": "440100000013200******",
"LATITUDE": "0.000000"
}, {
"DEVICE_TYPE": 194,
"DEVICE_STATUS": 0,
"LONGITUDE": "0.000000",
"DEVICE_NAME": "测试3",
"DEVICE_ADDR": "",
"DEVICE_ID_INT": "11",
"HAVE_VIDEO": "true",
"OWNER": "1",
"ORIGINAL_DEVICE_ID": "44010000001320******",
"PLATFORM_ID": "44000000052005******",
"ORG_CODE": "4401",
"TYPE": "1",
"DEVICE_ID": "44010000001320******",
"LATITUDE": "0.000000"
}],
"count": 3,
"usetime": 0
}
}

说是可能,是因为存在多种不同的返回结果,上述json消息中返回的有3个设备信息,但也可能是1个,也可能是2个,或者是更多,具体的数值要根据页面状况。我们的任务是从返回的json消息中提取所有的设备ID号(DEVICE_ID)。

个人认为,这种初始环境的不确定性本来是自动化测试的大忌,会给脚本的成功运行带来很大的风险,但在实际应用中,由于测试环境并非是个人独占的,每次测试时,页面配置的变化是可以理解的存在。为了提高脚本的健壮性,最好的办法是每次根据实际页面的返回值,提取其中的所有参数,然后拼接好,存jmeter的内部变量以供后续接口使用。要做好这一点,光用现成的jmeter工具,尤其是我们常用的json提取器(json extractor)肯定是无法做到了,至少做不到参数拼接后续处理。如果针对不同的场景,用if控制器来做区分,又会显得太累赘。

作为一个世界级的以java为基础的开源工具,肯定有其他的办法,个人感觉,jmeter搭载了beanshell就好像robot framework搭载了evaluate,一下子世界宽广了。作为一个半吊子,jmeter还没搞透彻,java也没用过,又要开始研究beanshell也是有点拼。只好求助万能的度娘。网上提到了一种beanshell postprocessor结合fastjson库的方法,可以做json的快速高效提取。

先把配置环境说一下,我用到的是jmeter5.0,fastjson用到的是1.2.47的版本,下载地址如下http://repo1.maven.org/maven2/com/alibaba/fastjson/1.2.47/,需要把下载下来的jar包放到jmeter的安装路径的lib/ext库中,并且在jmeter test plan中引用这个jar包

在需要提取的页面添加BeanShell后置处理器

script编写如下:

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
// 获取数据
//log.info("---something---");
String response = prev.getResponseDataAsString(); // 获取Response
//log.info("Respnse is " + response);
JSONObject responseObj = JSON.parseObject(response); // 整个Response作为JSON对象
JSONObject resObj = responseObj.getJSONObject("data"); // 获取某一部分对象。即,json串中{}的内容
//log.info("resObj is " + resObj);
JSONArray listArray = resObj.getJSONArray("records"); // 获取列表。即,json串中[]的内容
// 保存数据
// 1) 列表
//log.info("listArray is "+ listArray);
//log.info("array[0] is "+ listArray.getJSONObject(0).getString("DEVICE_ID"));
int len = listArray.size();
String[] temp = new String[len];
StringBuffer sBuffer = new StringBuffer("");
for(int i=0;i<len;i++){
temp[i]= listArray.getJSONObject(i).getString("DEVICE_ID");
sBuffer.append(temp[i]).append(",");
// log.info("sbuffer---"+sBuffer);
//vars.put("deviceId"+i, temp[i]);// 保存到JMeter变量中
//log.info("deviceIdAll===",deviceIdAll);
}
String keywordStr = sBuffer.deleteCharAt(sBuffer.length() - 1).toString();
vars.put("deviceId",keywordStr);

主要用到的API释义如下:

1. 将json字符串反序列化成JSON对象

JSONObject com.alibaba.fastjson.JSON.parseObject(String text)

2.根据key 得到json中的json数组

JSONArray com.alibaba.fastjson.JSONObject.getJSONArray(String key)

3. 根据下标拿到json数组的json对象

JSONObject com.alibaba.fastjson.JSONArray.getJSONObject(int index)

4.. 根据key拿到json的字符串值

String com.alibaba.fastjson.JSONObject.getString(String key)

更详细的fastjson的详细API参考了这篇文章:https://www.cnblogs.com/qiaoyeye/p/7730288.html

总结一下,此次踩过的坑主要有如下:

1.字符串是定义好之后就不能变更的,属于常量,和之前使用python的经验不同,在java中对于字符串,是不能使用拼接操作的,要不断写字符串,得用StringBuffer类。网上找到了这段话:

当对字符串进行修改的时候,需要使用 StringBuffer 和 StringBuilder 类。

和 String 类不同的是,StringBuffer 和 StringBuilder 类的对象能够被多次的修改,并且不产生新的未使用对象。

StringBuilder 类在 Java 5 中被提出,它和 StringBuffer 之间的最大不同在于 StringBuilder 的方法不是线程安全的(不能同步访问)。

由于 StringBuilder 相较于 StringBuffer 有速度优势,所以多数情况下建议使用 StringBuilder 类。然而在应用程序要求线程安全的情况下,则必须使用 StringBuffer 类。

2.运行时在控制台总是提示有这样的错误"Jmeter ERROR o.a.j.u.BeanShellInterpreter: Error invoking bsh method",我一直在怀疑是fastjson这个第三方库的使用有问题,最后发现是由于脚本中存在代码错误导致的,至于错误的原因,自己一行一行地找,所以在脚本中我加了无数的log.info,不得不说,beanshell脚本缺乏IDLE的编码环境,确实很不友好。

总之,通过这次的实践,进一步扩充了自己的知识面,再一次体会到,边走边看,坚持往前走的魅力所在。不要想着准备好所有的必要条件再出发,要用事情来推动自己去创造条件,任何经历都是成长。工作与生活皆如此!

 
 

jmeter中beanshell postprocessor结合fastjson库提取不确定个数的json参数的更多相关文章

  1. jmeter 之 BeanShell PostProcessor跨线程全局变量使用

    BeanShell PostProcessor是用户对一些变量的操作,操作方法很灵活,大概原理是通过parameters传回来对象,然后在script中对对象进行操作 场景:从登陆接口中获取token ...

  2. 『动善时』JMeter基础 — 31、JMeter中BeanShell断言详解

    目录 1.BeanShell简介 2.Beanshell的内置变量和方法 3.BeanShell断言界面详解 4.BeanShell断言的使用 (1)测试计划内包含的元件 (2)登陆接口请求界面内容 ...

  3. JMeter中BeanShell用法总结(一)

    一.什么是Bean Shell BeanShell是一种完全符合Java语法规范的脚本语言,并且又拥有自己的一些语法和方法; BeanShell是一种松散类型的脚本语言(这点和JS类似); BeanS ...

  4. JMeter中BeanShell的实际应用

    使用Jmeter的BeanShell断言,把响应数据中的JSON跟数据库中的记录对比 很多时候我们需要把Response Data取到的 Json 字符串跟数据库里的对比,来验证接口的正确性,使用Be ...

  5. JMeter中BeanShell实现写入文件

    1.首先F:\test.txt文件为空

  6. JMeter中BeanShell Sampler

    https://blog.51cto.com/11009785/2385492?source=dra 1.jmeter报错 jmeter.protocol.java.sampler.BeanShell ...

  7. JMeter中BeanShell Sampler调试分享

    BeanShell脚本 String s = "s"; String y = "y"; boolean result = s.equals(y); vars.p ...

  8. JMeter中BeanShell断言使用一

    Jmeter Ant Task如何让beanshell断言失败的详细信息展示在report里面 首先必须给beanshell断言添加FailureMessage if(${TotalClient_SS ...

  9. jmeter中beanshell断言的使用

    简单使用beanshell的内容,进行测试内容的判断 这里通过断言内容,修改if的条件,达到发送警报邮件的功能 beanshell 代码如下:     SampleResult 等效于 prev lo ...

随机推荐

  1. 201871030135-姚辉 实验二 个人项目—《D{0-1} KP》项目报告

    项目 内容 课程班级博客链接 课程班级博客链接 这个作业要求链接 这个作业要求链接 我的课程学习目标 (1)掌握软件项目个人开发流程.(2)掌握Github发布软件项目的操作方法. 这个作业在哪些方面 ...

  2. ASP.NET Core中使用令牌桶限流

    在限流时一般会限制每秒或每分钟的请求数,简单点一般会采用计数器算法,这种算法实现相对简单,也很高效,但是无法应对瞬时的突发流量. 比如限流每秒100次请求,绝大多数的时间里都不会超过这个数,但是偶尔某 ...

  3. Maven相关知识总结

    目录 认识Maven Maven下载安装 Maven能用来做什么 Maven核心概念 开发目录 坐标和仓库 POM文件 POM文件内容 Maven依赖管理 构建生命周期 构建多模块系统 聚合 继承 聚 ...

  4. Day05_22_实例化对象的JVM内存分析

    创建对象的 JVM 内存分析 *new 运算符的作用是创建对象,在JVM堆内存中开辟新的内存空间 *方法区内存:在类加载的时候,class字节码文件被加载到该内存空间当中 *栈内存(局部变量):方法代 ...

  5. Java并发的背景

    在操作系统中,并发是指一个时间段中有几个程序都处于已启动运行到运行完毕之间,且这几个程序都是在同一个处理机上运行,但任一个时刻点上只有一个程序在处理机上运行. 并发与操作系统的生命历程息息相关.进程的 ...

  6. 让我们一起建设 Vue DevUI 项目吧!🥳

    DevUI Design 是从华为云 DevCloud 众多业务孵化出来的一套设计体系,DevUI 倡导沉浸.灵活.至简的设计价值观,提倡设计者为真实的需求服务,为多数人进行设计,拒绝哗众取宠.取悦眼 ...

  7. [BUAA2021软工助教]案例分析作业总结

    目录 一.作业链接 二.优秀作业推荐 A+作业推荐 A作业推荐 三.总结 所有案例分析总结 特色与优点 问题与建议 不同类产品案例分析Bug汇总 CSDN问答社区.Stack Overflow.Seg ...

  8. [ssh登录]ssh登录报警

    1.报警脚本 mkdir /scripts vim /scripts/telegram_ssh.sh #!/bin/bash text="用户: $PAM_USER 用户IP: $PAM_R ...

  9. UVA10881蚂蚁

    题意:      在一个木棍上有只小蚂蚁,他们的移动速度都是1,移动的时候如果和别的蚂蚁碰面,那么碰面的这两只小蚂蚁会马上掉头继续走,给你每只蚂蚁的初始距离木棒左端点的距离和方向,以及木棍长度,问你t ...

  10. POJ2195费用流+BFS建图

    题意:       给你一个n*m的地图,上面有w个人,和w个房子,每个人都要进房子,每个房子只能进一个人,问所有人都进房子的路径总和最少是多少? 思路:       比较简单的最大流,直接建立两排, ...