抱歉,您的浏览器无法访问本站

本页面需要浏览器支持(启用)JavaScript


了解详情 >

一. 介绍BeanShell Sampler

来一段BeanShell 的说明。

是一种完全符合java语法规范的脚本语言,且又拥有自己的一些语法和方法;是一种松散类型的脚本语言;它执行标准java语句和表达式,另外它还包括一些脚本命令和语法

BeanShell有 以下几种:

  • 定时器: Beanshell Timer
  • 前置处理器:BeanShell PreProcessor
  • 后置处理器:BeanShell PostProcessor
  • 采样器:BeanShell Sampler
  • 断言: BeanShell
  • 监听器: BeanShell Listener

BeanShell Sampler是其中的一种,本篇只说BeanShell Sampler。

二.BeanShell Sampler的一些基本操作

2.1 变量的获取和赋值

BeanShell Sampler本身是支持java语法的,那么java中新建变量,变量传递那套也支持,就不多展开了。例如:

1
String name = "Mike";

但是这样的变量是无法被Jmeter的控制器直接使用的,需要通过put方法传递到变量或者属性中去。(如果不存在该变量或属性,会自动新建) props的使用没有这么简单,后面再细讲,这边只说它的get和put方法。

1
2
3
4
5
6
7
# 变量赋值
String name = "Mike";
vars.put("name", name);

# 属性赋值
String age = 15;
props.put("age", age);

对于或者属性的获取,使用get。紧急上面,我们创建了变量name和属性age,在别的BeanShell要使用,如下:

1
2
3
4
5
# 变量获取
vars.get("name")

# 属性获取
props.get("age")

2.2 变量,自定义变量和属性的作用域

在Test Plan自定义一个变量params。

image.png

新建两个线程组。 第一个线程组创建两个BeanShell Sample。 在第一个线程组的第一个BeanShell Sample打印params,然后使用put方法改变params的值。另外新建个变量params1。

image.png

在第一个线程组的第二个BeanShell Sample中使用vars获取变量,然后打印出来,以示区分,前面带上前缀。

image.png

在第二个线程组新建一个BeanShell Sample,内容同上。

image.png

运行结果如下。

image.png

按照顺序以下依次将BeanShell Sampler命名为BS1(线程组1),BS2(线程组1),BS3(线程组2)。

BS1中首先获取自定义的变量params赋值给了aa,打印aa,得到hehe。 然后通过vars.put改变了params的值为hahahaha,另外创建了一个变量params1为233333。

然后再同线程组的BS2下分别获取params和params1赋值给了aa和bb,通过打印结果可知,变量params是自定义变量,可以在同线程的不同BeanShell Sampler中传递,在BS2内打印aa已经是更改后的hahahaha,而在BS1中新建的params1赋值给bb后打印出来也取到了值:233333。

然后看BS3,BS3打印params(aa),结果是hehe,然后打印params1(bb) 也没取到值打印是null,说明不同线程组之间,vars的赋值无效。

那么props呢,在 BS1添加一步:props.put("params2", "hello");

image.png

在 BS2和BS3 分别打印一下,其中BS2 中打印完后更改下params2的值。

image.png image.png

执行结果:

image.png

我们发现,cc只在BS2中获取到然后打印出来,在BS3中也获取到了更改后的值并且打印了出来。

结论:

  • vars.put的作用范围只在当前线程组。
  • Test Plan中定义的自定义变量比较特殊,在不同线程组内都可以获取,但在一个线程组更改后影响不到另一个线程组。
  • props的作用范围是整个Test Plan,可以在不同线程组之间使用,更改其值会影响其他线程组的使用。

扩展:

在jmeter中,设置属性还可以通过内置函数来设置,例如设置一个属性name

1
2
3
4
5
${__setProperty(name,"john",)}
#这里john也可以换成另一个变量,例如${__setProperty(name,${x},)}

#使用
${__property(name)}

使用的时候,这样的语法可以直接写在其他控制器上,而不是局限于 BeanShell中。

image.png

2.3 打印方法

打印主要有三种方式:

  • log.info() 输出到当前jmeter.log
  • print() 输出打印到console.log
  • System.out.println() 输出打印到console.log

具体可参考下图。

image.png

2.4 引用外部Java文件

先写一个方法,例如add,另存为D:\MyClass.java

1
2
3
4
5
6
7
public class MyClass
{
public int add(int a, int b)
{
return a + b;
}
}

image.png

2.5 引用外部Class

1
2
3
4
5
6
7
8
package testmyclass;
public class MyClass
{
public int add(int a, int b)
{
return a + b;
}
}

然后BeanShell Sampler中,该种方法适用于有很多class在一个pacakge下的时候。

image.png

三.BeanShell Sampler使用场景介绍

在目前的压测脚本中,针对例如查询这样的接口,通过分析他的kibana日志,建立他的参数模型,那么可以得到用户在使用这个功能的时候,可能出现的不同场景的几率。例如默认查询占比30%,分页占10%,带条件查询占70%(就不细分条件组合了),那么在模拟的时候,我们需要考虑到这样的占比情况,最终我们模拟出来的访问情况要尽可能的贴近这样的比例。

使用随机数来是一种很好的实现方式,在BeanShell Sampler中通过每次随机数,按照数字的范围走执行相应http请求。这样的控制,单靠Jmeter本身提供的控制器无法实现,需要自定义脚本,结合一些逻辑控制器才能实现。

操作如下,新建一个线程组,然后新建一个BeanShell Sampler, 新建一个事务控制器。

image.png

在事务控制器里添加三个if逻辑控制器

image.png

分别命名为if1, if2, if3 image.png

在每个if控制器下都新建个http请求,然后给线程组添加一个聚合树报告。

最后结构如下

image.png

BeanShell Sampler实现代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
//从0~999之间随机一个数

${__Random(0,99,randomNum)};

//默认先将所有if控制器置为false,将不会被执行

vars.put("if1","false");
vars.put("if2","false");
vars.put("if3","false");


//通过每次随机数的范围,来打开某个if控制器,则对应的控制器下的内容将被执行

if(${randomNum}<33){
vars.put("if1","true");
}

if(${randomNum}>=34 && ${randomNum}<66){

vars.put("if2","true");
}

if(${randomNum}>=66){

vars.put("if3","true");
}

设置下下线程组的线程数和次数

image.png

执行后,查看聚合树报告。

image.png

可以看到,三个控制器下的请求执行次数约等于1:1:1,跟在BeanShell Sampler设置的比例接近。实际使用中,便可以参考此代码,通过扩大随机数范围或者增加执行次数等,来使得测试结果越来越接近实际比例。

评论