玩转jmeter:beanshell必备技能
beanshell是什么
BeanShell是一个小型嵌入式Java源代码解释器,能够动态地执行java代码。
下载及运行
下载地址:https://beanshell.github.io/download.html
java -jar直接运行
测试
其它方式启动:先把jar包加入到环境变量
界面UI方式 :java bsh.Console
命令行方式 :java bsh.Interpreter
运行脚本文件:java bsh.Interpreter filename [args]
第二个例子
运行结果
如果jar包没加到环境变量,可以这样运行:java -classpath %CLASSPATH%;bsh-2.0b4.jar bsh.Interpreter test.txt
jmeter中beanshell
而我们的jmeter中,已经自带了jar包,下面介绍jmeter中如何使用beanshell
添加变量
下面import的类,在jmeter的lib下:commons-codec-1.11.jar
引用变量
发送请求,可以看到密码加密了
自定义函数
上面也可以封装为函数
下面方法返回类型为void
import org.apache.commons.codec.digest.DigestUtils; public static void fun(){ String password_md5 = DigestUtils.md5Hex("123456"); vars.put("password_md5", password_md5); } fun();
下面方法返回类型为String
import org.apache.commons.codec.digest.DigestUtils; public static String fun(){ String password_md5 = DigestUtils.md5Hex("123456"); print(password_md5); // 在命令行窗口打印结果 return password_md5; } String password_md5 = fun(); vars.put("password_md5", password_md5);
也可以写成这样(方法不写返回类型)
import org.apache.commons.codec.digest.DigestUtils; fun(){ String password_md5 = DigestUtils.md5Hex("123456"); print(password_md5); // 在命令行窗口打印结果 return password_md5; } String password_md5 = fun(); vars.put("password_md5", password_md5);
甚至写成这样(定义的变量也没类型)
import org.apache.commons.codec.digest.DigestUtils; fun(){ String password_md5_res = DigestUtils.md5Hex("123456"); print(password_md5_res); // 在命令行窗口打印结果 return password_md5_res; } password_md5 = fun(); vars.put("password_md5", password_md5);
但是还是推荐按照java的方式写,严格定义。
引用java文件、class文件、jar文件
https://www.cnblogs.com/uncleyong/p/9429752.html
常用内置变量
JMeter在它的BeanShell中内置了变量,用户可以通过这些变量与JMeter进行交互。
log vars prev Failure FailureMessage
具体用法请百度,本篇的示例中也有使用到。
beanshell组件(beanshell取样器、beanshell前置处理器、beanshell断言)
Jmeter中包括多种BeanShell,用法差不多,只是作用的地方不同。
定时器: BeanShell Timer
前置处理器:BeanShell PreProcessor,提前处理请求参数,如:加密解密等
采样器: BeanShell Sampler
后置处理器:BeanShell PostProcessor,在请求后对返回结果进行处理
断言: BeanShell断言,验证返回结果的正确性
监听器: BeanShell Listener
下面举例几个常用的。
beanshell取样器
引用变量
发送请求,可以看到密码加密了
beanshell前置处理器
beanshell断言
断言--beanshell断言
样例一
补充:
public class JSONObject extends JSON implements Map<String, Object>, Cloneable, Serializable, InvocationHandler {}
JSON.parseObject(res)和JSONObject.parseObject(res)都是调用的JSON类的parseObject方法,JSONObject继承了类JSON
public static JSONObject parseObject(String text) { Object obj = parse(text); if (obj instanceof JSONObject) { return (JSONObject)obj; } else { try { return (JSONObject)toJSON(obj); } catch (RuntimeException var3) { throw new JSONException("can not cast to JSONObject.", var3); } } }
最简单的案例
{"code":"0","msg":"success"}
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; String res = prev.getResponseDataAsString(); String code = JSON.parseObject(res).getString("code"); log.info(code); String exp_result = "1"; if (!exp_result.equals(code)) { Failure = true; FailureMessage = "code与实际值不一致,期望值" + exp_result + ", 实际值" + code; } else{ System.out.println("pass"); }
如果字符串唯一,最好就用简单的文本断言
如果非唯一,得用bs断言,例如:
{"code":"0","msg":"success","data":{"code":"0","msg":"成功"}}
断言data里面的code
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; String res = prev.getResponseDataAsString(); String code = JSON.parseObject(res).getJSONObject("data").getString("code"); log.info(code); String exp_result = "1"; if (!exp_result.equals(code)) { Failure = true; FailureMessage = "code与实际值不一致,期望值" + exp_result + ", 实际值" + code; } else{ System.out.println("pass"); }
布尔值字段
{"code":"0","msg":"success","status":"false"}
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; String res = prev.getResponseDataAsString(); String status = JSON.parseObject(res).getString("status"); String exp_result = "true"; if (!exp_result.equals(status)) { Failure = true; FailureMessage = "status与实际值不一致,期望值" + exp_result + ", 实际值" + status; } else{ System.out.println("pass"); }
{"code":"0","msg":"success","status":false}
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; String res = prev.getResponseDataAsString(); //Boolean status = JSON.parseObject(res).getBoolean("status"); Boolean status = JSON.parseObject(res).getBooleanValue("status"); if (!status) { Failure = true; FailureMessage = "status实际值是" + status; } else{ System.out.println("pass"); }
样例二
pom依赖
<dependencies> <!-- https://mvnrepository.com/artifact/com.alibaba/fastjson --> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.49</version> </dependency> </dependencies>
代码及打的jar包
把jar包复制到jmeter的lib下ext中,重启jmeter
添加用户定义变量
请求
beanshell前置处理器,加密密码
beanshell断言,直接看最后if即可
另外:
获取对象类型:obj.getClass().toString();
Integer.valueOf返回的是Integer对象,Integer.parseInt返回的是int
完整脚本
import com.uncleyong.JsonToJSONObject; import com.alibaba.fastjson.JSONObject; // 不能少,下面定义了JSONObject类型 print("===========开始执行=========="); String exp_result = vars.get("exp_result"); print("exp_result= " + exp_result); print("exp_result的类型:" + exp_result.getClass().toString()); // exp_result的类型:class java.lang.String //Integer.valueOf返回的是Integer对象,Integer.parseInt返回的是int Integer exp_result2 = Integer.valueOf(exp_result); print("exp_result2的类型:" + exp_result2.getClass().toString()); // exp_result2的类型:class java.lang.Integer String jsonString = prev.getResponseDataAsString(); print("获取到的返回结果:" + jsonString); print("返回结果的类型:" + jsonString.getClass().toString()); // 返回结果的类型:class java.lang.String JSONObject responseJson = new JsonToJSONObject().JSONObjectUtil(jsonString); print("转换后的返回结果:" + responseJson); print("转换后的返回结果类型:" + responseJson.getClass()); // 转换后的返回结果类型:class com.alibaba.fastjson.JSONObject String code = responseJson.getString("code"); print("code = " + code); print("code的类型:" + code.getClass()); // code的类型:class java.lang.String Integer code2 = responseJson.getInteger("code"); print("code2 = " + code2); print("code2的类型:" + code2.getClass()); // code2的类型:class java.lang.Integer //if (code.equals(exp_result)==false) { if (code2 != exp_result3) { print("--------进入if语句--------"); Failure = true; FailureMessage = "code与实际值不一致,期望值" + exp_result + ", 实际值" + code; } print("===========结束执行==========");
运行结果
手把手实践
关联:https://www.cnblogs.com/uncleyong/p/14330102.html
《jmeter对接口测试入参进行MD5加密的5种方式》,详见微信公众号:全栈测试笔记
https://www.cnblogs.com/uncleyong/protected/p/9429752.html
《性能测试:jmeter中通过beanshell把关联转变成参数化》
https://www.cnblogs.com/uncleyong/p/10986466.html
__EOF__
关于博主:擅长性能、全链路、自动化、企业级自动化持续集成(DevTestOps)、测开等
面试必备:项目实战(性能、自动化)、简历笔试,https://www.cnblogs.com/uncleyong/p/15777706.html
测试提升:从测试小白到高级测试修炼之路,https://www.cnblogs.com/uncleyong/p/10530261.html
欢迎分享:如果您觉得文章对您有帮助,欢迎转载、分享,也可以点击文章右下角【推荐】一下!