性能工具之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 中。
相关推荐
qq_529025299 分钟前
Torch.gather
python·深度学习·机器学习
数据小爬虫@9 分钟前
如何高效利用Python爬虫按关键字搜索苏宁商品
开发语言·爬虫·python
禁默35 分钟前
深入浅出:AWT的基本组件及其应用
java·开发语言·界面编程
Cachel wood41 分钟前
python round四舍五入和decimal库精确四舍五入
java·linux·前端·数据库·vue.js·python·前端框架
Code哈哈笑44 分钟前
【Java 学习】深度剖析Java多态:从向上转型到向下转型,解锁动态绑定的奥秘,让代码更优雅灵活
java·开发语言·学习
終不似少年遊*1 小时前
pyecharts
python·信息可视化·数据分析·学习笔记·pyecharts·使用技巧
gb42152871 小时前
springboot中Jackson库和jsonpath库的区别和联系。
java·spring boot·后端
程序猿进阶1 小时前
深入解析 Spring WebFlux:原理与应用
java·开发语言·后端·spring·面试·架构·springboot
Python之栈1 小时前
【无标题】
数据库·python·mysql