一、什么是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元件都有自己的内置对象,在元件上也有对应说明,当前元件的内置对象有哪些,比如BeanShell Sampler元件的底部有提示该元件有哪些内置对象。

十七、Jmeter BeanShell使用_是Bean Shell BeanShel

这里先介绍常用的内置对象。

 

log 记录日志,Jmeter使用log4j记录日志,一般使用的比较多的是log.info()、log.error(),打印的日志会记录到bin/jmeter.log文件
props 操作Jmeter属性,即jmeter.properties文件的配置
  props.get("https.use.cached.ssl.context"): 获取对应的属性值
  props.put("https.use.cached.ssl.context", false): 保存数据到Jmeter属性中,如果属性不存在就创建
vars 是类JMeterVariables的对象,具体内部方法使用,请看 
操作Jmeter变量,需要注意Jmeter变量是在线程启动时,拷贝到线程的,类似线程的局部变量,所以一个线程更新了变量,不会影响到另一个线程
  vars.get("name"): 从线程中获得变量值
  vars.put("key", "value"): 保存数据到线程中,如果变量不存在会创建
ctx 是类JMeterContext的对象,保存线程的上下文,该对象不是线程安全的,建议在单线程时使用,具体内部方法使用,请看
prev 是类SampleResult的对象,保存前一个请求的信息,具体内部方法使用,请看 
注意
根据作用域和执行顺序 可以知道,元件有在采样器前执行的,有在采样器后执行的,对于在采样器前执行的,prev表示的是前一个请求的信息,而对于在采样器后执行的,prev表示的当前请求的信息!
data 类型是byte[],即字节数组,
当前请求的响应数据,可以用String str = new String(data, "utf-8")转成字符串再打印出来

四、常见BeanShell 元件介绍

1.BeanShell Sampler

十七、Jmeter BeanShell使用_是Bean Shell BeanShel_02
 
Reset bsh.Interpreter before each call(2):勾选后,线程每次循环前重置变量。但这个我勾选了之后,循环也没有重置变量。不知道是不是Jmeter文档没更新的原因。
Parameters(3):传递给BeanShell脚本的参数,只能传递String字符串类型。有两种方式使用:
          Parameters:单个字符串,则使用Parameters;
          bsh.args:数组,空白处分割,比如a b c,那么bsh.args[0]=a。
Script file(4):包含要运行的BeanShell脚本的文件,文件名存储在变量FileName中,添加了脚本文件后,就只会运行添加的脚本文件,Script部分的脚本代码不会运行了。
Script(5):要运行的BeanShell脚本,返回值如果不为null,就存储为采样器结果。
内置对象(6):

 

SampleResult 是类SampleResult的对象,保存当前请求和响应的信息,具体内部方法使用,请看
ResponseCode 响应的status code,默认为200
ResponseMessage 响应信息,默认为"OK"
IsSuccess 请求是否成功,默认为true
Label 采样器的标签,即Name字段
FileName 文件名,如果Script file有包含外部bsh文件

2.BeanShell PreProcessor

假设现在有一个登录HTTP接口,且这个登录接口对密码做了Base64加密,这个时候我们要测试这个登录接口,就可以使用BeanShell前置处理器  ,先利用脚本将密码做Base64加密,HTTP采样器中再使用密码这个变量的值。
十七、Jmeter BeanShell使用_是Bean Shell BeanShel_03
Reset bsh.Interpreter before each call(1):和BeanShell Sampler中的2一样,True表示勾选。

内置对象(4):

 

 

3.BeanShell PostProcessor

BeanShell后置处理器,可以用于处理响应数据。比如现在有一个接口返回的数据数据是加密的,也可以在后置处理器里先对响应数据做解密。

十七、Jmeter BeanShell使用_是Bean Shell BeanShel_04
如果我们要认为修改响应数据,那么就可以通过prev这个对象来修改,prev是SampleResult的对象,查看SampleResult类的文档,可以看到一个方法:
十七、Jmeter BeanShell使用_是Bean Shell BeanShel_05
那么我们现在就通过BeanShell PostProcessor来将接口的返回数据修改为"Hello, World",写入如下代码:
byte[] b = "Hello,World".getBytes();
prev.setResponseData(b);
十七、Jmeter BeanShell使用_是Bean Shell BeanShel_06
 

4.BeanShell Timer

定时器会让作用域内的每一个采样器都在执行前等待一个固定的时长,如果作用域内有多个定时器,那这多个定时器就会在采样器之前全部执行,所以多个定时器的延迟时长是每个定时器的延时时长的累加。

十七、Jmeter BeanShell使用_是Bean Shell BeanShel_07

现在,我们想要一个采样器延迟3秒再执行,写入如下代码:

// 单位是毫秒
Thread.sleep(3000);

从日志文件bin/jmeter.log中可以看到采样器延迟了3秒。

5.BeanShell Assertion

十七、Jmeter BeanShell使用_是Bean Shell BeanShel_08

可以看到BeanShell断言的内置对象很多,可读/可写的意思是我们可以更改,比如说SampleResult是当前请求响应的数据,说白了,在BeanShell断言里同样可以修改响应数据,和BeanShell后置处理器一样。

Failure boolean,用来设置断言状态,为true,表明断言失败
FailureMessage String,用来设置断言信息
SampleResult SampleResult,具体内部方法,请看
Response SampleResult,具体内部方法,请看
ResponseData byte[],响应数据
ResponseCode String,status code的值,比如200,404
ResponseMessage String,响应信息,比如OK
ResponseHeaders String,响应头
RequestHeaders String,请求头
SampleLabel String,采样器的Name
SamplerData String,就是截图中的内容

现在我们用ResponseCode来判断,等于200时,设置为通过,写入如下代码:

if ("200".equals(""+ResponseCode) == false )
{
    // 响应码不等于200时,设置断言失败,并输出失败信息
    Failure=true ;
    FailureMessage ="Response code was not a 200 response code it was " + ResponseCode + "." ;
    print ( "the return code is " + ResponseCode);   // this goes to stdout
    log.warn( "the return code is " + ResponseCode); // this goes to the JMeter log file
} else {
    // 响应码等于200时,设置断言成功,并输出成功信息
    Failure=false;
    FailureMessage = "Return true, and the response code was " + ResponseCode;
     }

十七、Jmeter BeanShell使用_是Bean Shell BeanShel_09

6.BeanShell Listener

十七、Jmeter BeanShell使用_是Bean Shell BeanShel_10

内置对象:

 

BeanShell监听器用相比较而言比较少

五、编写脚本

例如:现在线程有两个变量username=Augus,new_name=ls,我们需要读取username将new_name修改为"Hello, Augus"。

1、设置变量username=Augus,new_name=ls:
Jmeter设置变量的方式一共有4种:
1)Test Plan的User Defined Variables,
2)Config Element的User Defined Variables ,
3)Config Element的CSV Data Set Config,
4)Pre Processors的User Parameters
这里就直接使用Test Plan的User Defined Variables了

2、添加一个Sampler --> Debug Sampler,命名为before,其他配置保持默认即可,这只是用来查看变量修改前的值。
3、添加一个Sampler --> BeanShell Sampler,并先写入如下脚本:
public static void test(){
//定义一个变量
String inout;
//获取变量aa所对应的值,赋值给input
input = vars.get("username");
String output = "hello," + input;
vars.put("new_name",output);
}

test()

4、添加一个Sampler --> Debug Sampler,命名为after
5、添加一个Listener --> View Results Tree
6、运行,查看结果:

十七、Jmeter BeanShell使用_是Bean Shell BeanShel_11
十七、Jmeter BeanShell使用_是Bean Shell BeanShel_12
 
上面已经实现了修改变量值,现在我想把这段代码提取到一个Java的方法里,之后再在BeanShell Sampler中直接使用。
BeanShell中引用外部类,有三种方法:
1)引用源文件,即.java文件。
2)引用字节码文件,即.class文件。
3)引用jar包,即.jar文件。
现在先新建一个BeanShellMethod.java文件,并写入如下代码:
public class BeanShellMethod {
    public static String test(String input) {
        String output = "hello," + input;
        return output;    
    }
}

引用源文件

Jmeter提供了source函数,来引用源文件。在BeanShell Sampler中写入如下代码:

//加载使用java文件
source("D:\\jmeterBeanShell\\BeanShellMethod.java");

//获取变量aa所对应的值
String str1 = vars.get("username");

//调用java文件中test函数,对于
String str2 = new BeanShellMethod().test(str1);

//保存值
vars.put("password",str2);

运行,从after中可以看到new_name变量被修改了。

十七、Jmeter BeanShell使用_是Bean Shell BeanShel_13

 

引用字节码文件

上面我们有了BeanShellMethod.java,可以将其编译为后缀为.class的字节码文件,方式如下:

javac BeanShellMethod.java

十七、Jmeter BeanShell使用_是Bean Shell BeanShel_14

十七、Jmeter BeanShell使用_是Bean Shell BeanShel_15

Jmeter提供了addClassPath函数,来引用字节码文件。在BeanShell Sampler中写入如下代码:

//加载class文件的路径
addClassPath("D:\\jmeterBeanShell");

//注意这里导入类,注意也有加;
import BeanShellMethod;

//获取aa变量的值
String str1 = vars.get("username");

//调用test方法
String str2 = new BeanShellMethod().test(str1);

//赋值保存
vars.put("new_name",str2);

运行,从after中可以看到new_name变量被修改了。

十七、Jmeter BeanShell使用_是Bean Shell BeanShel_16

引用外部jar包

Jmeter引用外部jar包方法:将jar包拷贝到jmeter/lib/ext目录下,这种需要重启Jmeter,才能加载这个jar包;

首先编辑java文件,然后再将.class文件打包成jar包,再将jar包拷贝到对应目录.然后在BeanShell Sampler中写入如下代码:

import hellotest.BeanShellMethod;

//获取aa变量的值
String str1 = vars.get("username");

//调用test方法
String str2 = new hellotest.BeanShellMethod().test(str1);

//赋值保存
vars.put("new_name",str2);

运行,从after中可以看到new_name变量被修改了。

十七、Jmeter BeanShell使用_是Bean Shell BeanShel_17

六、其它用法(接受参数, log等)

1、在Test Plan中定义如下三个变量:

十七、Jmeter BeanShell使用_是Bean Shell BeanShel_18

2、Bean Shell可脚本如下:

  • a、bean shell可以接受传入参数,如下图:${name} ${age} ${sex}
  • b、参数可以通过bsh.args[]按顺序提取
  • c、bean shell提供了一个内置变量Parameters,来保存参数的集合
//获取参数传递过来的值并存入变量中
vars.put("v1",bsh.args[0]);
vars.put("v2",bsh.args[1]);
vars.put("v3",bsh.args[2]);

//获取参数传递过来的变量集合
vars.put("v4",Parameters);

//输出变量集合
log.info(Parameters);

//输出该元件的name
log.info(Label);

//设置响应代码
ResponseCode = 500;

//设置响应信息
ResponseMessage = "This is a BeanShell test";

//设置是否成功
IsSucces = false;

//设置响应数据
SampleResult.setResponseData("hello world")

十七、Jmeter BeanShell使用_是Bean Shell BeanShel_19

3、运行结果如下图:

十七、Jmeter BeanShell使用_是Bean Shell BeanShel_20

下图中1输入的这两句设置:

ResponseCode = 500;
ResponseMessage = ResponseMessage = "This is a BeanShell test";

十七、Jmeter BeanShell使用_是Bean Shell BeanShel_21

下图中2输入的这两句设置:

这里需要注意,点击【选项】,勾选log Viewer,然后运行,可以查看运行的日志信息

//输出变量集合
log.info(Parameters);

//输出该元件的name
log.info(Label);

 

十七、Jmeter BeanShell使用_是Bean Shell BeanShel_22