性能工具之JMeter 通过Java API生成 BeanShell PreProcessor 脚本

文章目录

一、前言

对于上一篇文章(性能工具之 HAR 格式化转换JMeter JMX 脚本文件)还是有点问题。大家在使用的情况需要注意。

如果多个接口相同 path 路径且不同参数进行查询如:

上面接口如果不做处理生成脚本:

展开几个看看:

再点击下一个观察:

如果把上面脚本构建成一个接口,相同参数通过 CSV Data Set Config 或者其他参数文件方式处理就能实现这一想法,这里演示怎么通过BeanShell PreProcessor 来处理这样的想法。

二、实现代码

为了通过代码自动构建 BeanShell PreProcessor 脚本,将相同路径但不同参数的请求构建为一个参数数组,并通过随机数据给每次请求,我们可以按照以下步骤进行:

详细步骤:

  1. 创建 BeanShell PreProcessor:
  2. 创建一个 BeanShell PreProcessor 实例,并设置其脚本内容。
  3. 脚本内容将负责生成随机参数数组,并将这些参数传递给请求。
  4. 生成随机参数数组: 在脚本中生成随机参数数组,并将这些参数赋值给变量。
java 复制代码
import java.util.Random;

Random rand = new Random();
String[] dictCodeStr = { "s_cache=17","s_cache","s" };
int randomIndex = rand.nextInt(dictCodeStr.length);
vars.put("paramPath", String.valueOf(dictCodeStr[randomIndex]));

将这些变量传递给请求。

  • 组装测试计划:
    将 BeanShell PreProcessor 和请求(例如 HTTPSampler)组装到测试计划中。

详细代码实现:

java 复制代码
BeanShellPreProcessor  beanShellPreProcessor = new BeanShellPreProcessor ();
beanShellPreProcessor.setName("BeanShell PreProcessor");
beanShellPreProcessor.setScript("sdsd");
beanShellPreProcessor.setComment("参数化文件");
beanShellPreProcessor.setProperty(BeanShellTestElement.TEST_CLASS, BeanShellPreProcessor.class.getName());
beanShellPreProcessor.setProperty(BeanShellTestElement.GUI_CLASS, TestBeanGUI.class.getName());
HashTree testPlanTreeShell = new HashTree();
testPlanTreeShell.add(beanShellPreProcessor);
threadGroupHashTree.add(baiducomSampler, testPlanTreeShell);

执行后发现脚本没有写入任何数据,再次修改脚本为:

上面写入成功。

基于上面脚本可以修改成我们想要的脚本文件如:

java 复制代码
// 构建 shell 脚本
    String beanShellScript = "import java.util.Random;\n" +
            "\n" +
            "   Random rand = new Random();\n" +
            "   String[] dictCodeStr = {paramList};\n" +
            "   int randomIndex = rand.nextInt(dictCodeStr.length);\n" +
            "   vars.put(\"paramPath\", String.valueOf(dictCodeStr[randomIndex]));";

    ArrayList<String> paraList = new ArrayList<>();
    paraList.add("s_cache=1726989090167&s_locale=zh-cn");
    paraList.add("s_cache=1726989090168&s_locale=zh-cn");
    beanShellScript = beanShellScript.replace("paramList", JSONObject.toJSONString(paraList).replace("[", "").replace("]", ""));

    BeanShellPreProcessor  beanShellPreProcessor = new BeanShellPreProcessor ();
    beanShellPreProcessor.setName("BeanShell PreProcessor");
    beanShellPreProcessor.setComment("参数化文件");
    beanShellPreProcessor.setResetInterpreter(false);
    beanShellPreProcessor.setProperty("parameters", "");
    beanShellPreProcessor.setProperty("filename", "");
    beanShellPreProcessor.setProperty("script", beanShellScript);
    beanShellPreProcessor.setProperty(BeanShellTestElement.TEST_CLASS, BeanShellPreProcessor.class.getName());
    beanShellPreProcessor.setProperty(BeanShellTestElement.GUI_CLASS, TestBeanGUI.class.getName());
    baiducomSampler.setPath("/" + "${paramList}");
    HashTree testPlanTreeShell = new HashTree();
    testPlanTreeShell.add(beanShellPreProcessor);

执行JAVA代码:

成功转换成想要的参数文件。

三、代码示例

全部参考代码,如下:

java 复制代码
// 初始化压测引擎 
StandardJMeterEngine jmeter = new StandardJMeterEngine();

 // JMeter初始化(属性、日志级别、区域设置等)
 JMeterUtils.setJMeterHome(jmeterHome.getPath());
 JMeterUtils.loadJMeterProperties(jmeterProperties.getPath());
 // 可以注释这一行,查看额外的日志,例如DEBUG级别
 JMeterUtils.initLogging();
 JMeterUtils.initLocale();

 // Test Plan 测试计划
 TestPlan testPlan = new TestPlan("创建JMeter脚本");
 testPlan.setProperty(TestElement.TEST_CLASS, TestPlan.class.getName());
 testPlan.setProperty(TestElement.GUI_CLASS, TestPlanGui.class.getName());
 testPlan.setUserDefinedVariables((Arguments) new ArgumentsPanel().createTestElement());

 // Loop Controller 循环控制
 LoopController loopController = new LoopController();
 loopController.setLoops(1);
 loopController.setFirst(true);
 loopController.setProperty(TestElement.TEST_CLASS, LoopController.class.getName());
 loopController.setProperty(TestElement.GUI_CLASS, LoopControlPanel.class.getName());
 loopController.initialize();

 // Thread Group 线程组
 ThreadGroup threadGroup = new ThreadGroup();
 threadGroup.setName("Example Thread Group");
 threadGroup.setNumThreads(1);
 threadGroup.setRampUp(1);
 threadGroup.setSamplerController(loopController);
 threadGroup.setProperty(TestElement.TEST_CLASS, ThreadGroup.class.getName());
 threadGroup.setProperty(TestElement.GUI_CLASS, ThreadGroupGui.class.getName());

 // JMeter测试计划,基本上是JOrphan HashTree
 HashTree testPlanTree = new HashTree();
 // 从以上初始化的元素构造测试计划
 testPlanTree.add(testPlan);
 HashTree threadGroupHashTree = testPlanTree.add(testPlan, threadGroup);

 // 第一个 HTTP Sampler - 打开 baidu.com
 HTTPSamplerProxy baiducomSampler = new HTTPSamplerProxy();
 baiducomSampler.setDomain("baidu.com");
 baiducomSampler.setPort(80);
 baiducomSampler.setPath("/");
 baiducomSampler.setMethod("GET");
 baiducomSampler.setName("Open baidu.com");
 baiducomSampler.setProperty(TestElement.TEST_CLASS, HTTPSamplerProxy.class.getName());
 baiducomSampler.setProperty(TestElement.GUI_CLASS, HttpTestSampleGui.class.getName());

 // 构建 shell 脚本
 String beanShellScript = "import java.util.Random;\n" +
         "\n" +
         "   Random rand = new Random();\n" +
         "   String[] dictCodeStr = {paramList};\n" +
         "   int randomIndex = rand.nextInt(dictCodeStr.length);\n" +
         "   vars.put(\"paramPath\", String.valueOf(dictCodeStr[randomIndex]));";

 ArrayList<String> paraList = new ArrayList<>();
 paraList.add("s_cache=1726989090167&s_locale=zh-cn");
 paraList.add("s_cache=1726989090168&s_locale=zh-cn");
 beanShellScript = beanShellScript.replace("paramList", JSONObject.toJSONString(paraList).replace("[", "").replace("]", ""));

 BeanShellPreProcessor  beanShellPreProcessor = new BeanShellPreProcessor ();
 beanShellPreProcessor.setName("BeanShell PreProcessor");
 beanShellPreProcessor.setComment("参数化文件");
 beanShellPreProcessor.setResetInterpreter(false);
 beanShellPreProcessor.setProperty("parameters", "");
 beanShellPreProcessor.setProperty("filename", "");
 beanShellPreProcessor.setProperty("script", beanShellScript);
 beanShellPreProcessor.setProperty(BeanShellTestElement.TEST_CLASS, BeanShellPreProcessor.class.getName());
 beanShellPreProcessor.setProperty(BeanShellTestElement.GUI_CLASS, TestBeanGUI.class.getName());
 baiducomSampler.setPath("/" + "${paramList}");
 HashTree testPlanTreeShell = new HashTree();
 testPlanTreeShell.add(beanShellPreProcessor);

 threadGroupHashTree.add(baiducomSampler, testPlanTreeShell);

 // 将生成的测试计划保存为JMeter的.jmx文件格式
 SaveService.saveTree(testPlanTree, new FileOutputStream("D:\\work\\jmx" + slash + "example1.jmx"));

四、最后

希望上面代码对大家有参考价值。

顺便问下,如果想解决下面接口我们应该怎么处理呢?

这里提供一个思路:

  1. 解析上面参数到一个对象中。
  2. 按 path 路径进行分组。
  3. 构建 jmx脚本,通过 path 路径获取分组后的参数文件构建 buildBeanShellScript 。
  4. 添加到 HashTree 中。
相关推荐
Boilermaker19928 分钟前
【Java EE】Mybatis-Plus
java·开发语言·java-ee
noravinsc23 分钟前
django 一个表中包括id和parentid,如何通过parentid找到全部父爷id
python·django·sqlite
xdscode29 分钟前
SpringBoot ThreadLocal 全局动态变量设置
java·spring boot·threadlocal
lifallen32 分钟前
Paimon 原子提交实现
java·大数据·数据结构·数据库·后端·算法
ajassi200034 分钟前
开源 python 应用 开发(三)python语法介绍
linux·python·开源·自动化
丶小鱼丶40 分钟前
链表算法之【合并两个有序链表】
java·算法·链表
沉默媛1 小时前
如何安装python以及jupyter notebook
开发语言·python·jupyter
张先shen1 小时前
Elasticsearch RESTful API入门:全文搜索实战(Java版)
java·大数据·elasticsearch·搜索引擎·全文检索·restful
天河归来2 小时前
springboot框架redis开启管道批量写入数据
java·spring boot·redis
张先shen2 小时前
Elasticsearch RESTful API入门:全文搜索实战
java·大数据·elasticsearch·搜索引擎·全文检索·restful