性能工具之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 中。
相关推荐
渣哥2 分钟前
Java Set 不会重复?原来它有“记仇”的本事!
java
一叶飘零_sweeeet2 分钟前
从 0 到 1 攻克订单表分表分库:亿级流量下的数据库架构实战指南
java·数据库·mysql·数据库架构·分库分表
掘技术4 分钟前
十个 Python 案例分享
python
苹果醋36 分钟前
数据库索引设计:在 MongoDB 中创建高效索引的策略
java·运维·spring boot·mysql·nginx
Dontla17 分钟前
Dockerfile解析器指令(Parser Directive)指定语法版本,如:# syntax=docker/dockerfile:1
java·docker·eureka
彭于晏Yan19 分钟前
SpringBoot优化树形结构数据查询
java·spring boot·后端
AAA修煤气灶刘哥35 分钟前
缓存这「加速神器」从入门到填坑,看完再也不被产品怼慢
java·redis·spring cloud
练习时长一年41 分钟前
Spring事件监听机制(三)
java·后端·spring
月阳羊42 分钟前
【硬件-笔试面试题-69】硬件/电子工程师,笔试面试题(知识点:电机驱动电路的反馈电路)
java·经验分享·嵌入式硬件·面试
2301_781392521 小时前
用spring框架实现简单的MVC业务
java·后端·spring