Jmeter5.2.1
JDK1.8
BeanShell是一种完全符合Java语法规范的脚本语言,是轻量级的Java脚本,所以BeanShell和Java是可以无缝衔接的。
BeanShell的特点:
1、完整的Java语法的动态执行,Java代码片段,以及松散类型的Java和其他脚本
2、透明地访问所有Java对象和API
我对BeanShell的理解是:Java代码的脚本形式。
Java对格式的要求很严格,必须按照规定的格式编写,编译时才能通过,比如一个Java类:
public class HuMan{
// 属性
private Integer gender;
// 方法
public Integer getGender() {
return this.gender;
}
}
那么如果我想打印Hello, World,在BeanShell和Java中该怎么写呢?
// Java[Application这个类名是随便定的]
public class Application {
public static void main(String[] args) {
System.out.println("Hello, world");
}
}
// BeanShell
// 注意这里的打印是打印到Jmeter的控制台了
System.out.println("Hello, World");
以上两个例子就很明显的体现了BeanShell是轻量级的Java脚本了,不用再拘泥于各种格式,同时BeanShell又能访问Java对象和API,所以在Jmeter中可以利用BeanShell来调用一些我们自己写好的Java类。
那么Jmeter中有哪些BeanShell?
1、定时器:BeanShell Timer
2、前置处理器:BeanShell PreProcessor
3、采样器:BeanShell Sampler
4、后置处理器:BeanShell PostProcessor
5、断言:BeanShell Assertion
6、监听器:BeanShell Listener
BeanShell内置对象
其中,每个BeanShell元件都有自己的内置对象,在元件上也有对应说明,当前元件的内置对象有哪些,比如BeanShell Sampler元件的底部有提示该元件有哪些内置对象。
这里先介绍常用的内置对象。
BeanShell Sampler
元件介绍
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):
编写脚本
写到这里,我们对BeanShell Sampler也有一些了解了,那么现在就开始来写一些脚本吧,首先先明确脚本要实现什么?在初学阶段,可以从修改变量开始。
假设:现在线程有一个变量username=jack,我们需要将username修改为"Hello, jack"。
1、设置变量username=jack:
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了,设置username=jack。
2、添加一个Sampler --> Debug Sampler,命名为before,其他配置保持默认即可,这只是用来查看变量修改前的值。
3、添加一个Sampler --> BeanShell Sampler,并先写入如下脚本:
String username = vars.get("username");
String new_username = "Hello," + username;
vars.put("username", new_username);
4、添加一个Sampler --> Debug Sampler,命名为after
5、添加一个Listener --> View Results Tree
6、运行,查看结果:
现在我们已经实现了修改变量值,现在我想把这段代码提取到一个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中写入如下代码:
// 路径写入BeanShellMethod.java文件的绝对路径
source("/Users/Local/jmeter/scripts/BeanShellMethod.java");
String input = vars.get("username");
// BeanShellMethod.java中我们把test方法定义为static的,所以这里直接通过类名来调用就可以了
String output = BeanShellMethod.test(input);
vars.put("username", output);
运行,从after中可以看到username变量被修改了。
引用字节码文件
Jmeter提供了addClassPath函数,来引用字节码文件。首先先编译java文件,具体命令可百度搜索。
然后在BeanShell Sampler中写入如下代码:
addClassPath("/Users/zhoubihui/Local/jmeter/scripts");
import BeanShellMethod;
String input = vars.get("username");
String output = BeanShellMethod.test(input);
vars.put("username", output);
运行,从after中可以看到username变量被修改了。
引用外部jar包
Jmeter引用外部jar包有两种方法:
1)将jar包拷贝到jmeter/lib/ext目录下,这种需要重启Jmeter,才能加载这个jar包;
2)Test Plan --> Add directory or jar to classpath中添加,这种不需要重启Jmeter。
首先编辑java文件,然后再将.class文件打包成jar包,再将jar包拷贝到对应目录,或者在Test Plan中添加。
然后在BeanShell Sampler中写入如下代码:
import BeanShellMethod;
String input = vars.get("username");
String output = BeanShellMethod.test(input);
vars.put("username", output);
BeanShell PreProcessor
假设现在有一个登录HTTP接口,且这个登录接口对密码做了Base64加密,这个时候我们要测试这个登录接口,就可以使用BeanShell前置处理器 戳此回顾 ,先利用脚本将密码做Base64加密,HTTP采样器中再使用密码这个变量的值。
Reset bsh.Interpreter before each call(1):和BeanShell Sampler中的2一样,True表示勾选,但是我实践了发现没起作用。
内置对象(4):
BeanShell PostProcessor
BeanShell后置处理器,可以用于处理响应数据。比如现在有一个接口返回的数据里,我只需要拿到id,那么就可以在后置处理器里先处理response。或者接口返回的数据是加密的,也可以在后置处理器里先对响应数据做解密。
如果我们要认为修改响应数据,比如上面我举的例子,我只想要响应数据里的id,那么就可以通过prev这个对象来修改,prev是SampleResult的对象,查看SampleResult类的文档,可以看到一个方法:
那么我们现在就通过BeanShell PostProcessor来将接口的返回数据修改为"Hello, World",写入如下代码:
byte[] b = "Hello,World".getBytes();
prev.setResponseData(b);
BeanShell Timer
定时器会让作用域内的每一个采样器都在执行前等待一个固定的时长,如果作用域内有多个定时器,那这多个定时器就会在采样器之前全部执行,所以多个定时器的延迟时长是每个定时器的延时时长的累加。
戳此回顾 作用域和执行顺序。
现在,我们想要一个采样器延迟2秒再执行,写入如下代码:
// 单位是毫秒
Thread.sleep(2000);
从日志文件bin/jmeter.log中可以看到采样器延迟了2秒。
BeanShell Assertion
可以看到BeanShell断言的内置对象很多,可读/可写的意思是我们可以更改,比如说SampleResult是当前请求响应的数据,说白了,在BeanShell断言里同样可以修改响应数据,和BeanShell后置处理器一样。
那么,我们现在先和BeanShell后置处理器中一样,只把响应修改为"Hello, World",写入如下代码:
byte[] b = "Hello, World".getBytes();
SampleResult.setResponseData(b);
可以看到BeanShell断言同样可以实现修改响应数据,不过修改响应数据还是放在BeanShell后置处理器中比较好,不同的元件负责不同的功能,断言就只做断言判断。
现在我们用ResponseCode来判断,等于200时,设置为断言失败,写入如下代码:
if ("200".equals(ResponseCode)) {
Failure = true;
FailureMessage = "心情不好";
}
断言失败的,在查看结果树会标红显示:
BeanShell Listener
内置对象:
BeanShell监听器我用的少,平时用View Results Tree、Summary Report比较多,网上也没找到比较好的文章,所以这部分只能先写到这了。
BeanShell的使用先介绍到这了,下一节介绍JSR223和groovy。