JMeter:测试计划中如何随机且仅一次使用vms_lst_前缀属性值
嘿,我来帮你搞定这个需求!结合你的场景(多线程+多循环、随机不重复取值),咱们分两步走:先把REST响应里的目标值存成vms_lst_前缀的属性,再实现安全的随机不重复取值逻辑。
第一步:从REST响应提取值,存储为
vms_lst_前缀属性 你可以用BeanShell PostProcessor挂在返回VM列表的REST请求下面,把响应里的每个VM值单独存成vms_lst_1、vms_lst_2这类属性,同时记录总数量方便后续遍历。
举个JSON响应的例子(如果是XML响应,换成XML解析逻辑就行):
// 导入JSONPath工具(JMeter通常自带,若没有需额外添加依赖) import com.jayway.jsonpath.JsonPath; // 获取REST响应内容 String responseBody = prev.getResponseDataAsString(); // 用JSONPath提取VM列表,替换成你实际的JSON路径 List<String> vmNames = JsonPath.read(responseBody, "$.data.vms[*].name"); // 循环存储每个VM为vms_lst_前缀的属性 for (int i = 0; i < vmNames.size(); i++) { String propName = "vms_lst_" + (i + 1); vars.put(propName, vmNames.get(i)); } // 存储VM总数,后续取值要用 vars.put("vms_lst_total", String.valueOf(vmNames.size()));
如果要让所有线程组都能访问这些属性,把vars.put换成props.put(props是JMeter全局属性)。
第二步:多线程下随机不重复取值
在需要调用API的请求前,加一个BeanShell PreProcessor,实现每个线程维护自己的“已使用VM索引”列表,确保每个值只被当前线程用一次,同时随机选取。代码如下:
import java.util.ArrayList; import java.util.Random; // 获取VM总数 int totalVMs = Integer.parseInt(vars.get("vms_lst_total")); // 初始化当前线程的已使用索引集合(线程隔离,不会和其他线程冲突) if (vars.getObject("used_vm_indices") == null) { vars.putObject("used_vm_indices", new ArrayList<Integer>()); } ArrayList<Integer> usedIndices = vars.getObject("used_vm_indices"); // 所有VM都用完时的处理:这里选重置列表,你也可以改成终止线程 if (usedIndices.size() >= totalVMs) { log.info("当前线程的VM已全部使用,重置已使用列表"); usedIndices.clear(); } // 生成随机索引,直到找到未使用的 Random random = new Random(); int pickedIndex; do { pickedIndex = random.nextInt(totalVMs) + 1; // 对应vms_lst_1、vms_lst_2的序号 } while (usedIndices.contains(pickedIndex)); // 标记该索引为已使用 usedIndices.add(pickedIndex); // 获取选中的VM值,存成变量供后续API调用 String targetVM = vars.get("vms_lst_" + pickedIndex); vars.put("selected_vm", targetVM);
之后你的API请求里直接用${selected_vm}就能拿到随机且不重复的VM值了。
额外注意点
- 如果是分布式测试(多机器跑JMeter),线程级的
used_vm_indices就不够用了,得用外部存储(比如Redis)来记录全局已使用的VM,避免不同机器重复取值。 - 确保提取VM的请求在所有需要取值的线程组之前执行,或者用全局属性
props存储vms_lst_系列属性,保证所有线程都能读到。
内容的提问来源于stack exchange,提问作者Ilan Z
相关产品推荐
相关产品推荐

