Jmeter-Bean shell

本文介绍了BeanShell的基本概念,它是一种轻量级的Java脚本语言,适用于JMeter性能测试工具。文章详细讲解了如何使用BeanShellPreProcessor进行密码的加解密,并列举了BeanShell中的常用内置变量。

一、什么是Bean Shell

  • BeanShell是一种完全符合Java语法规范的脚本语言,并且又拥有自己的一些语法和方法;
  • BeanShell是一种松散类型的脚本语言(这点和JS类似);
  • BeanShell是用Java写成的,一个小型的、免费的、可以下载的、嵌入式的Java源代码解释器,具有对象脚本语言特性,非常精简的解释器jar文件大小为175k。
  • BeanShell执行标准Java语句和表达式,另外包括一些脚本命令和语法。

官网:http://www.BeanShell.org/

 

二、Jmeter有哪些Bean Shell

  • 定时器:  BeanShell Timer

  • 前置处理器:BeanShell PreProcessor

  • 采样器:  BeanShell Sampler

  • 后置处理器:BeanShell PostProcessor

  • 断言:   BeanShell断言

  • 监听器:  BeanShell Listener

 

三、BeanShell的用法

   在此介绍下BeanShell PreProcessor的用法,其它的beahshell可以类推。在此我们使用beahshell调用自己写的工具类,工具类实现了密码的加、解密功能:

1、在eclipse写好代码,然后把该类打成jar包(在类上点击右键->Export->jar file)

2、把jar包放到jmeter目录\apache-jmeter-2.13\lib\ext下

3、打开jmeter,添加一个http sampler(调用登录接口),在sampler下添加一个BeanShell PreProcessor

4、在beanshell PreProcessor中导入我们的jar包,调用里面的加、解密码方法,把结果保存在jmeter变量中,下面两个方法是beanshell中我们最常用到的:

  • vars.get(String paramStr):获得变量值
  • vars.put(String key,String value):,将数据存到jmeter变量中

复制代码
import com.pingan.ff.account.user.utils.*;

//加密
System.out.println(“加密”);
String password = “123123”;
String encode = SecurityUtils.getKey(password);//调用工具类中的方法进行加密
System.out.println(“Set my encode”);
vars.put(“encode”,encode);//把值保存到jmeter变量encode中
String getEncode=vars.get(“encode”);
System.out.println("Get my encode: " + getEncode);

复制代码

5、把加密后的密码存到jmeter变量中,然后在http sampler中就可以通过${encode}进行使用了:

6、执行脚本:

 

四、Bean Shell常用内置变量

    JMeter在它的BeanShell中内置了变量,用户可以通过这些变量与JMeter进行交互,其中主要的变量及其使用方法如下:

  • log:写入信息到jmeber.log文件,使用方法:log.info(“This is log info!”);

  • ctx:该变量引用了当前线程的上下文,使用方法可参考:org.apache.jmeter.threads.JMeterContext

  • vars - (JMeterVariables):操作jmeter变量,这个变量实际引用了JMeter线程中的局部变量容器(本质上是Map),它是测试用例与BeanShell交互的桥梁,常用方法:

    a) vars.get(String key):从jmeter中获得变量值

    b) vars.put(String key,String value):数据存到jmeter变量中

    更多方法可参考:org.apache.jmeter.threads.JMeterVariables

  • props - (JMeterProperties - class java.util.Properties):操作jmeter属性,该变量引用了JMeter的配置信息,可以获取Jmeter的属性,它的使用方法与vars类似,但是只能put进去String类型的值,而不能是一个对象。对应于java.util.Properties。 

    a) props.get("START.HMS");  注:START.HMS为属性名,在文件jmeter.properties中定义 

    b) props.put("PROP1","1234"); 

  • prev - (SampleResult):获取前面的sample返回的信息,常用方法:

    a) getResponseDataAsString():获取响应信息

    b) getResponseCode() :获取响应code

    更多方法可参考:org.apache.jmeter.samplers.SampleResult

  • sampler - (Sampler):gives access to the current sampler

官网:

http://jmeter.apache.org/usermanual/component_reference.html#BeanShell_Sampler

http://jmeter.apache.org/usermanual/component_reference.html#BeanShell_PreProcessor

<think>我们正在讨论JMeter中的BeanShell断言使用方法及常见问题。根据引用[1]和引用[2],我们可以总结如下: BeanShell断言是JMeter中一种强大的自定义断言方式,允许用户使用Java语法编写脚本来验证响应结果。它通过设置内置变量`Failure`和`FailureMessage`来标识断言成功或失败,并可以自定义返回信息。 ### 一、BeanShell断言基本使用方法 1. **添加BeanShell断言** -JMeter中,右键点击需要断言的HTTP请求(或其他采样器)→ 添加 → 断言 → BeanShell断言。 2. **编写断言脚本** -BeanShell断言的脚本编辑区,可以编写自定义的Java语法脚本。例如: ```java // 导入JSON处理包(如需要) import org.json.*; // 获取响应数据 String responseData = prev.getResponseDataAsString(); try { // 解析JSON JSONObject jsonObj = new JSONObject(responseData); int status = jsonObj.getInt("status"); // 验证状态码是否为200 if (status != 200) { Failure = true; // 断言失败 FailureMessage = "状态码错误,期望200,实际为:" + status; } else { Failure = false; // 断言成功(可省略,因为默认是false) // 可以设置成功信息,但注意:默认断言结果监听器不显示成功 // 可以通过日志输出成功信息 log.info("✅ 断言成功:状态码为200"); } } catch (Exception e) { Failure = true; FailureMessage = "JSON解析失败: " + e.getMessage(); } ``` 3. **内置变量和对象**(重要) - `Failure`: 布尔值,设置为`true`表示断言失败,`false`表示成功(默认是`false`)。 - `FailureMessage`: 字符串,自定义的失败信息,在断言失败时显示。 - `SampleResult`: 当前采样结果对象,可通过它获取响应数据、响应时间等。 - `ResponseCode`: 响应码(字符串)。 - `ResponseMessage`: 响应消息(字符串)。 - `log`: 日志对象,可以写日志(如`log.info("...")`)。 - `vars`: JMeter变量操作对象(如`vars.get("varName")`获取变量)。 - `props`: JMeter属性操作对象。 ### 二、常见问题及解决方案 1. **问题:断言结果监听器不显示成功信息** - **原因**JMeter默认只记录失败的断言,成功的断言不会在断言结果监听器中显示。 - **解决**- 使用`log.info()`输出成功信息到日志(如上例)。 - 添加其他监听器(如“查看结果树”或“简单数据写入器”)并配置记录成功结果。 2. **问题:JSON解析失败(如无法导入org.json包)** - **原因**JMeter默认不包含json.org的jar包。 - **解决**- 下载`json.jar`(如json-20210307.jar)并放入JMeter的`lib`目录,重启JMeter- 或者使用JMeter内置的`org.apache.jmeter.util.JMeterUtils`解析JSON(需要手动解析字符串,不推荐)。 3. **问题:BeanShell脚本性能较差** - **原因**BeanShell解释执行,效率较低。 - **解决**- 对于高并发测试,改用JSR223断言(使用Groovy语言),Groovy编译执行,性能更好。 - 精简脚本,避免在循环中创建大对象。 4. **问题:如何获取响应数据?** - 使用`prev.getResponseDataAsString()`获取字符串形式的响应体。 - 使用`prev.getResponseData()`获取字节数组。 5. **问题:多个BeanShell断言覆盖问题** - **现象**:一个采样器添加了多个BeanShell断言,但只有最后一个断言的`FailureMessage`被记录。 - **原因**JMeter中同一个采样器的多个断言,如果都失败,默认只记录最后一个断言的失败信息。 - **解决**- 将多个断言合并到一个BeanShell断言中,通过逻辑判断多个条件。 - 或者使用不同的监听器分别记录(如分离到不同线程组)。 6. **问题:如何验证响应头?** - 使用`prev.getResponseHeaders()`获取整个响应头字符串。 - 或者使用`prev.getHeaderManager().getHeader("HeaderName")`获取特定响应头(需要先保存为变量)。 ### 三、高级用法示例:验证复杂JSON数组 ```java import org.json.*; String response = prev.getResponseDataAsString(); try { JSONArray items = new JSONArray(response); int expectedCount = 5; // 期望数组长度为5 if (items.length() != expectedCount) { Failure = true; FailureMessage = "数组长度应为" + expectedCount + ",实际为" + items.length(); } else { // 遍历验证每个元素 for (int i = 0; i < items.length(); i++) { JSONObject item = items.getJSONObject(i); if (!item.has("id")) { Failure = true; FailureMessage = "元素" + i + "缺少id字段"; break; } } // 如果没有触发失败,则标记成功 if (!Failure) { log.info("✅ 断言成功:数组结构正确"); } } } catch (JSONException e) { Failure = true; FailureMessage = "JSON解析异常: " + e.getMessage(); } ``` ### 四、性能优化建议 1. **避免在断言中处理大量数据**:如果响应体很大(如超过1MB),解析JSON会消耗大量内存和CPU。 2. **使用条件判断提前退出**:在循环中一旦发现错误立即退出。 3. **改用JSR223+Groovy**:性能比BeanShell高10倍以上[^3]。 4. **减少日志输出**:避免在循环中输出日志,否则会极大降低性能。 --- ### 相关问题 1. 如何在JMeter中安装JSON库以支持BeanShell断言? 2. JSR223断言与BeanShell断言在性能上有何差异? 3. 如何通过BeanShell断言验证数据库查询结果? 4. JMeter中如何实现跨采样器的断言(如一个事务包含多个请求)? 5. 如何将BeanShell断言中的错误信息保存到外部文件? [^1]: jmeter BeanShell断言 的使用方法(一) [^2]: JmeterBeanShell断言使用</think>### JMeter BeanShell断言使用指南 #### 一、基本使用方法 1. **添加断言位置** - 右键点击HTTP请求 → 添加 → 断言 → BeanShell断言 - 推荐添加监听器:**断言结果****查看结果树** 2. **核心脚本结构** ```java import org.json.*; // 引用[1]提到的JSON解析包 // 获取响应数据 String responseData = prev.getResponseDataAsString(); try { JSONObject json = new JSONObject(responseData); String actualValue = json.get("status").toString(); // 断言逻辑 if (!"200".equals(actualValue)) { Failure = true; // 标记断言失败 FailureMessage = "状态码错误! 期望:200, 实际:" + actualValue; // 引用[2]的自定义消息机制 } else { // 成功时可记录日志 log.info("✅ 断言成功: status=200"); } } catch (Exception e) { Failure = true; FailureMessage = "JSON解析失败: " + e.getMessage(); } ``` 3. **关键内置变量** - `Failure`:断言状态(true=失败,false=成功) - `FailureMessage`:自定义失败信息 - `ResponseData`:响应内容(字节数组) - `SampleResult`:采样结果对象 - `log`:日志记录器 #### 二、常见问题解决 1. **JSON解析失败** **原因**:缺少JSON库 **解决方案**: ```java // 手动添加依赖 @Grab('org.json:json:20210307') import org.json.*; ``` 或下载[json.jar](https://repo1.maven.org/maven2/org/json/json/20210307/json-20210307.jar)放入`jmeter/lib`目录 2. **断言不生效** **排查步骤**: ```mermaid graph TB A[检查脚本语法错误] --> B[查看jmeter.log] B --> C{是否有异常堆栈} C -->|是| D[修正脚本错误] C -->|否| E[确认Failure变量赋值] E --> F[检查监听器配置] ``` 3. **性能问题** **优化方案**- 避免在循环中创建大对象(如`new JSONObject()`) - 改用JSR223断言+Grovvy语言(性能提升5-10倍) - 使用`SampleResult.setIgnore()`跳过不必要响应 4. **变量作用域问题** **正确用法**: ```java // 获取JMeter变量 String expectValue = vars.get("expected_status"); // 设置变量供后续使用 vars.put("assert_result", "success"); ``` #### 三、高级应用场景 1. **数据库断言** ```java import java.sql.*; String dbUrl = "jdbc:mysql://localhost:3306/test"; try (Connection conn = DriverManager.getConnection(dbUrl, "user", "pass")) { ResultSet rs = conn.createStatement().executeQuery("SELECT status FROM orders"); rs.next(); if (!"completed".equals(rs.getString(1))) { Failure = true; FailureMessage = "数据库状态校验失败"; } } ``` 2. **跨请求断言** ```java // 获取其他请求的响应 String prevResponse = vars.getObject("OTHER_REQUEST").getResponseDataAsString(); ``` 3. **动态路径断言** ```java // 使用正则提取变量 String dynamicPath = vars.get("orderId") + ".status"; String jpath = "$." + dynamicPath; ``` #### 四、最佳实践 1. **错误处理规范** ```java try { // 业务逻辑 } catch (JSONException e) { FailureMessage = "JSON格式错误: " + e.getMessage(); } catch (Exception e) { FailureMessage = "系统异常: " + e.getClass().getSimpleName(); } finally { if (FailureMessage != null) Failure = true; } ``` 2. **调试技巧** - 临时添加调试输出: `log.info("当前响应: " + new String(ResponseData));` - 在查看结果树中启用`BeanShell PostProcessor` 3. **性能监控指标** | 指标 | 安全阈值 | 风险值 | |---|---|----| | 脚本执行时间 | < 5ms | > 20ms | | 内存消耗 | < 50KB | > 200KB | | CPU占用率 | < 2% | > 10% | > 注:通过`JMeterPlugins`的`PerfMon`监听器实时监控资源消耗 --- ### 相关问题 1. 如何将BeanShell断言升级为JSR223断言提升性能? 2. JMeter中如何实现跨线程组的断言验证? 3. BeanShell断言在分布式测试中需要注意哪些问题? 4. 如何通过BeanShell断言实现文件内容校验? 5. JMeter中如何捕获BeanShell断言的异常堆栈信息? [^1]: jmeter BeanShell断言 的使用方法(一) [^2]: JmeterBeanShell断言使用
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值