在写JMeter脚本的时候经常需要模拟一些数据,大部分情况下模拟数据一般采用“CSV Data Set Config”从CSV文件中取数据。但是使用数据文件的问题是不灵活,有多少虚拟用户可能得准备多少测试数据。比如,某应用的用户注册过程需要提供手机号码,如果采用CSV文件,需要测试1000虚拟用户则需要准备1000个手机号码,如果测试过程中要增加虚拟用户数目,则需要准备更多的测试数据,这个过程比较费事。对于某些特殊的有规律的测试数据,我们可以采用动态生成测试数据的方式,比如利用本文介绍的BeanShell。
具体需求
某手机应用的用户注册过程需要提供手机号码,测试场景中除了用户注册过程中会被用到之外,不会对手机号码产生实际操作行为(比如发送短信等),只需要符合在数据库中表的定义即可(11位char类型)。
实现
实现过程需要考虑不同的虚拟用户在运行的时候不能产生相同的号码,另外还需要考虑同一个虚拟用户在多次循环执行的情况下也不能产生相同的号码。为了实现上述需求,我们需要有一个标识虚拟用户的ID,以及在多次循环执行的情况下标识的当前循环次数的值。
标识虚拟用户可以通过JMeter的内置function - threadNum来得到,而后者可以通过JMeter提供的计数器来实现,先来看一下我们的脚本的结构。“HTTP请求”需要拿到手机号码发起一个测试请求,该手机号码是从一个名为mobile的JMeter变量里取得的,而该变量是通过“BeanShell PreProcessor”处理之后保存到JMeter的变量里。
BeanShell的实现,具体请看下面的代码注释。
import java.text.DecimalFormat;
String strThreadNum = "${__threadNum}"; //取得当前的虚拟用户ID
int thNum = Integer.parseInt(strThreadNum);
String str = "${iterNO}"; //取得该虚拟用户当前的循环次数
int i = Integer.parseInt(str);
int mobileNumLastFive = thNum * 10000 + i;
DecimalFormat df = new DecimalFormat( "0000000000" );
String fullNum = 4 + df.format(mobileNumLastFive); //格式化成4开头的11位手机号码
System.out.println(fullNum);
vars.put("mobile", fullNum); //将手机号码存入名为mobile的变量,该变量可以在“HTTP请求”中用到
计数器的定义:如下图所示,引用名称是在BeanShell里引用的iterNO变量。
BeanShell实现的方式的问题在于不是很高效,为了提高效率可以采用JMeter的function来实现,读者可以参考这篇文章。