概述
BeanShell是一个小型嵌入式Java源代码解释器,具有对象脚本语言特性,能够动态地执行标准JAVA语法,并利用在JavaScript和Perl中常见的的松散类型、命令、闭包等通用脚本来对其进行拓展。BeanShell不仅仅可以通过运行其内部的脚本来处理Java应用程序,还可以在运行过程中动态执行你java应用程序执行java代码。因为BeanShell是用java写的,运行在同一个虚拟机的应用程序,因此可以自由地引用对象脚本并返回结果
beanshell在jmeter中体现有:BeanShell PreProcessor、BeanShell Sampler、BeanShell PostProcessor、__BeanShell函数、BeanShell Timer 、BeanShell断言、BeanShell Listener,在这里都是可以直接return的。
注意:BeanShell Timer 、BeanShell断言、BeanShell Listener在此不做详细介绍,使用前面几个举例子
BeanShell PreProcessor内置变量
log:用来记录日志文件,写入到jmeber.log文件,参考 org.apache.log.Logger
官网给出是slf4j.Logger 我查检查了jar包,没有发现什么异常,如果有哪位发现是什么问题,请指正
ctx:(JmeterContext)通过它来访问context,参考:org.apache.jmeter.threads.JMeterContext
- vars - (JMeterVariables):操作jmeter变量,提供读取/写入访问变量的方法。参考org.apache.jmeter.threads.JMeterVariables
这个变量实际引用了JMeter线程中的局部变量容器(本质上是Map),它是测试用例与BeanShell交互的桥梁 - props - (JMeterProperties - class Java.util.Properties):操作jmeter属性,该变量引用了JMeter的配置信息,可以获取Jmeter的属性,它的使用方法与vars类似,但是只能put进去String类型的值,而不能是一个对象。对应于java.util.Properties。
- prev:获取前面的sample采样的结果,参考:org.apache.jmeter.samplers.SampleResult
- sampler: 访问当前采样,参考 org.apache.jmeter.samplers.Sampler
在测试计划中创建一个前置处理器(beanshell preProcessor),编写如下脚本,能涵盖到常规用法,更详细的请参考对API
//log:org.apache.log.Logger 常用
log.info("message info");
log.debug("message debug");
//log.error("message error");
log.warn("message warn");
//ctx:org.apache.jmeter.threads.JMeterContex
log.info("sample name:"+ctx.getCurrentSampler().getName());
//vars:org.apache.jmeter.threads.JMeterVariables
String string = "hello world";
byte[] bytes = string.getBytes();
vars.putObject("testObj",bytes);
vars.put("test","abc");
byte[] res=(byte[])vars.getObject("testObj");
for(int i=0;i<res.length;i++){
log.info("vars.get(\"testObj\")["+i+"]="+res[i]);
}
log.info("vars.get(\"test\")="+vars.get("test"));
//prev:org.apache.jmeter.samplers.SampleResult
//这里是获取前一个取样器的结果,若没有,会报空指针,最简单的办法线程组至少运行2次,第二次即可获取
try{
log.info("prev.getThreadName()="+prev.getThreadName());
}catch(Exception e){
e.printStackTrace();
}
//sampler:org.apache.jmeter.samplers.Sampler
log.info("sampler.getName()="+sampler.getName());
BeanShell PostProcessor
相对preProcessor,内置变量去掉了sampler,增加data,在此只说data,其他参考preProcessor
data:保存response内容,是一个byte[],保存的是取样器的结果,一般要对结果做特殊处理的时候使用,比如要取出来后做二次加工或者将部分内容定制化输出等……
新建BeanShell PostProcessor
System.out.println(ctx.getCurrentSampler().getName()+" ======Start======");
for(int i=0;i<data.length;i++){
System.out.print(((char)data[i]).toString());
}
System.out.println(ctx.getCurrentSampler().getName()+" ======End======");
__BeanShell函数
函数里面写入响应的表达式,可以引用BeanShell中的变量等,可以直接使用的变量比较多 参考BeanShell Sampler
- log 打印日志 log.info(“在控制台打印日志”);
- SampleResult 获取SampleResult对象,可以通过这个对象获取想要的信息
- Response 获取Response对象,可以通过这个对象获取对应的信息
- Failure 查看接口调用是否成功,如果返回false是成功的,true是失败的
- FailureMessage 失败信息,没有设置的时候失败信息是空的。可以set这个信息
- ResponseData 获取 response body 类型是byte[]
- ResponseCode 返回接口code 成功是200
- ResponseMessage 获取msg 成功是OK
- ResponseHeaders 获取接口服务端返回的头部信息
- RequestHeaders 获取客户端请求的头部信息
- SampleLabel 获取接口请求的名称
- SamplerData 获取请求的url和body
- ctx 代表上下文信息,可以直接使用
- vars 可以直接调用,将获取的数据变成jmeter变量(put),也可以获取用户自定义的变量(get)
栗子
preProcessor、postProcessor、BeanShell函数与普通取样器传参
- 新建测试计划
- 新建beanshell preProcessor
//log:org.apache.log.Logger 常用
log.info("message info");
log.debug("message debug");
//log.error("message error");
log.warn("message warn");
//ctx:org.apache.jmeter.threads.JMeterContex
log.info("sample name:"+ctx.getCurrentSampler().getName());
//vars:org.apache.jmeter.threads.JMeterVariables
String string = "hello world";
byte[] bytes = string.getBytes();
vars.putObject("testObj",bytes);
vars.put("test","abc");
byte[] res=(byte[])vars.getObject("testObj");
for(int i=0;i<res.length;i++){
log.info("vars.get(\"testObj\")["+i+"]="+res[i]);
}
log.info("vars.get(\"test\")="+vars.get("test"));
//prev:org.apache.jmeter.samplers.SampleResult
//这里是获取前一个取样器的结果,若没有,会报空指针,最简单的办法线程组至少运行2次,第二次即可获取
try{
log.info("prev.getThreadName()="+prev.getThreadName());
}catch(Exception e){
e.printStackTrace();
}
//sampler:org.apache.jmeter.samplers.Sampler
log.info("sampler.getName()="+sampler.getName());
return "测试而已,在此可有可无";
- 新建beanshell postProcessor
System.out.println(ctx.getCurrentSampler().getName()+" ======Start======");
for(int i=0;i<data.length;i++){
System.out.print(((char)data[i]).toString());
}
System.out.println(ctx.getCurrentSampler().getName()+" ======End======");
- 新建BeanShell Sampler
在该案例中直接返回,不写任何内容
return "不啰嗦,直接返回!!"
- 新建线程组并新建http请求 设置运行两次
参数kw的值是BeanShell表达式,取值为在preProcessor中放入的参数testObj
参数test的值是普通表达式,取值为在preProcessor中放入的参数test
beanshell中可以写更复杂的例子如定义方法,引入外部类等
引入外部类几种方式
- 复杂的打成jar
- 在测试计划中引入jar
- 把jar所在路径加入到可执行路径 addClassPath()
- 简单的单类也可以使用source()引入
孤立的类
public class JmeterBeanShellSourceTest {
public static int add(int a,int b) {
return a+b;
}
public void sayhello(String name) {
System.out.println("source hi "+name);
}
}
打成jar包
/**
* @Title: JmeterBeanShellTest.java
* @Package com.dangdang
* @Description: TODO
* @author yueling yueling@dangdang.com
* @date 2018年6月29日 下午1:09:50
* @version V1.0
*/
package com.dangdang;
/**
* @ClassName: JmeterBeanShellTest
* @Description: TODO
* @author yueling
* @date 2018年6月29日 下午1:09:51
*
*/
public class JmeterBeanShellTest {
public static int add(int a,int b) {
return a+b;
}
public void sayhello(String name) {
System.out.println("hi "+name);
}
}
在之前的测试计划上做如下修改:
- 引入jar包
- 修改BeanShell PreProcessor
import com.dangdang.JmeterBeanShellTest;
//log:org.apache.log.Logger 常用
log.info("message info");
log.debug("message debug");
//log.error("message error");
log.warn("message warn");
//ctx:org.apache.jmeter.threads.JMeterContex
log.info("sample name:"+ctx.getCurrentSampler().getName());
//vars:org.apache.jmeter.threads.JMeterVariables
String string = "hello world";
byte[] bytes = string.getBytes();
vars.putObject("testObj",bytes);
vars.put("test","abc");
byte[] res=(byte[])vars.getObject("testObj");
for(int i=0;i<res.length;i++){
log.info("vars.get(\"testObj\")["+i+"]="+res[i]);
}
log.info("vars.get(\"test\")="+vars.get("test"));
//prev:org.apache.jmeter.samplers.SampleResult
//这里是获取前一个取样器的结果,若没有,会报空指针,最简单的办法线程组至少运行2次,第二次即可获取
try{
log.info("prev.getThreadName()="+prev.getThreadName());
}catch(Exception e){
e.printStackTrace();
}
//sampler:org.apache.jmeter.samplers.Sampler
log.info("sampler.getName()="+sampler.getName());
source("d:\\JmeterBeanShellSourceTest.java");
int sourceresult=JmeterBeanShellSourceTest.add(1,2);
JmeterBeanShellSourceTest jmeterBeanShellSourceTest = new JmeterBeanShellSourceTest();
jmeterBeanShellSourceTest.sayhello("tom");
log.info("source result="+String.valueOf(sourceresult));
JmeterBeanShellTest jmeterBeanShellTest = new JmeterBeanShellTest();
int result=jmeterBeanShellTest.add(1,2);
jmeterBeanShellTest.sayhello("tom");
log.info("result="+String.valueOf(result));
return "测试而已,在此可有可无";