性能测试工具:jmeter 正则表达式,你可能只知其一
Posted 软件测试资源站
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了性能测试工具:jmeter 正则表达式,你可能只知其一相关的知识,希望对你有一定的参考价值。
重要测试资料包,不容错过
————
一、 背景
为了让大家更加的了解Jmeter,并且使用起来游刃有余,后期会加入性能篇。
1、Debug Sampler和Dummy Sampler
首先介绍一下Jmeter调试的利器 Debug Sampler和Dummy Sampler
Debug Sampler会把我们自定义的变量输出在Response Data中,方便我们调试的时候使用,正式执行脚本时需要删除Debug Sampler。
Dummy Sampler可以比较方便地模拟测试场景,自定义Request Data和Response Data,在学习测试脚本编写的过程中非常有用。当然,在写文章时又不能把公司的接口暴露了,打码打太多又不舒服,这时候Dummy Sampler使用起来也很舒服。
2、查看结果树& Log Viewer
使用监听器->查看结果树,方便查看接口的详情
打开选项->Log Viewer,方便调试beanshell脚本
二、json数据的提取
json数据:
{ "resultCode": "1000", "resultMsg": "success", "userdic": { "Ali": "Moubao" }, "userlist": [ { "firstName": "Jiezai", "lastName": "Grizz", "id": 6 }, { "firstName": "Ben", "lastName": "Rose", "id": 8 } ] }
配置Dummy Sampler的Request Data和Response Data都是上面的json串
我们演示一下提取userlist第一个firstName的值 Jiezai,提取userlist第二个firstName的值 Ben,提取userlist所有firstName的值 ["Jiezai","Ben"]
演示之前先讲一下我们会用到的JSON Path Extractor(这也是一个Jmeter扩展的第三方插件)的语法
$代表整个对象,.代表绝对路径,..代表相对路径,[0]代表取list的第一个值,[0,1]和[:2]都代表取list前两个元素
$.userlist
$.userlist[*]
$.userlist[-1:]
$..userlist[?(@.id>7)]
$..firstName
五个表达式的输出依次如下:
》》[{"firstName":"Jiezai","lastName":"Grizz","id":6},{"firstName":"Ben","lastName":"Rose","id":8}]
》》[{"firstName":"Jiezai","lastName":"Grizz","id":6},{"firstName":"Ben","lastName":"Rose","id":8}]
》》[{"firstName":"Ben","lastName":"Rose","id":8}]
》》[{"firstName":"Ben","lastName":"Rose","id":8}]
》》["Jiezai","Ben"]
PS:
1、 正则表达式提取器-》value = "(.+?)"-》模板$1$
():封装了待返回的匹配字符串。 .:匹配任何单个字符串。
+:一次或多次。 ?:在找到第一个匹配项后停止。
2、 JSON Path Extractor使用-》可参考:http://goessner.net/articles/JsonPath/
看了之后就知道关于提取其几乎无所不能,因为它像Xpath一样有自己的语法。
1、 提取userlist第一个firstName的值Jiezai
这个大家应该很在行,用过Jmeter提取json数据的都知道
使用正则表达式提取器:"firstName":"(.+?)"
Debug Sampler中提取结果test3=Jiezai
使用JSON Path Extractor
JsonPath表达式:$..userlist.firstName[0]
Debug Sampler中提取结果test3=Jiezai
2、 提取userlist第二个firstName的值Ben
使用正则表达式提取器:"firstName":"(.+?)"
或使用正则表达式提取器:"firstName":"(.+?)"*"firstName":"(.+?)"
说明一下,模板代表取正则表达式的第几个"(.+?)"
JsonPath表达式:$..userlist.firstName[1]
,图略。
Debug Sampler中提取结果test4=Ben
3、提取userlist所有firstName的值["Jiezai","Ben"]
只用一次正则表达式好像实现不了,但是使用JSON Path Extractor可以
JsonPath表达式:$..userlist.firstName
Debug Sampler中提取结果test1=["Jiezai","Ben"]
4、比较正则表达式提取器和JSON Path Extractor
正则表达式可以提取非json数据,JSON Path Extractor只能提取json数据(专业的),但我们一般HTTP请求的返回都是json格式,因为简洁直观。
当json数据返回值为{"firstName": "Jiezai"}
,正则表达式为"firstName": "(.+?)"
,如果:(冒号左右边有空格时),其实也是json数据,然后正则表达式也需要跟着加,但是不管冒号左右边有没有空格,JSON Path Extractor表达式都为$..firstName
三、时间偏移
1、使用BeanShell和javascript
因为公司涉及保险业务,保险期限和犹豫期都会用到时间偏移。
比如我买保险,保险期限一年,保险开始日期是当前日期2018-4-11,则结束日期是当前日期往后推一年 2019-4-11
。开始日期我们可以用BeanShell表达式
${__BeanShell(${__time(yyyy)})}-${__BeanShell(${__time(MM)},)}-${__BeanShell(${__time(dd,)})}
-->输出当前日期 2018-4-11 或者JavaScript表达式
${__javaScript((new Date().getFullYear())+'-'+(new Date().getMonth())+'-'+(new Date().getDate()),)}
-->输出当前日期 2018-4-11 如果往后推一年两个月加三天呢?
BeanShell表达式
${__BeanShell(${__time(yyyy)}+1,)}-${__BeanShell(${__time(MM,)}+2,)}-${__BeanShell(${__time(dd,)}+3,)}
JavaScript表达式
${__javaScript((new Date().getFullYear()+1)+'-'+(new Date().getMonth()+2)+'-'+(new Date().getDate()+3),)}
输出都是 2018-5-14
看起来好像是没问题,但是不然,因为当今天是 2018-12-30
时,上面的表达式结果就是 2019-14-33,哈哈哈,表达式不知道一年有多少个月,一个月有多少天,只会简单的往上加。但是如果只是年的偏移上面的表达式还是可以用,如果有月或者天的偏移我们可以借助BeanShell Sampler,其实就是执行Java代码。
2、使用BeanShell脚本
想执行BeanShell脚本可以使用BeanShell PreProcessor,BeanShell Sampler或BeanShell PostProcessor
执行顺序:BeanShell PreProcessor > BeanShell Sampler > BeanShell PostProcessor
BeanShell PreProcessor是前置处理器,在接口调用前执行,我这里就是用的这个
BeanShell Sampler是一个接口请求,会在结果树中体现并写入接口执行报告,只是像执行Java代码计算时间偏移不推荐使用。
BeanShell PostProcessor是后置处理器,在接口调用后执行。
举个例子:
只要BeanShell PreProcessor和 BeanShell PostProcessor在BeanShell Sampler的作用域下,就肯定是BeanShell PreProcessor
第一个运行,BeanShell Sampler
第二个运行,BeanShell PostProcessor
第三个运行。
BeanShell PreProcessor的Java源码:
import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date;log.info(Label); //输出原件的名称try{ log.info("*****时间偏移*****"); //输出日志 Date date =new Date(); //获取当前时间 SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd"); String nowDate = sf.format(date); Calendar cal = Calendar.getInstance(); cal.setTime(sf.parse(nowDate));//初始化为当前时间 cal.add(Calendar.DAY_OF_YEAR,+1); //后一天 String orderDate = sf.format(cal.getTime()); cal.setTime(sf.parse(nowDate)); cal.add(Calendar.DAY_OF_YEAR,+365); //后365天,即一年 String mouthDate = sf.format(cal.getTime()); vars.put("dayDate",orderDate);//把beanshell的变量传给Jmeter vars.put("yearDate",mouthDate); log.info("输出计算后的两个时间"); log.info("dayDate="+orderDate); log.info("yearDate="+mouthDate); } catch(Exception e){ }
时间偏移的执行结果图:
我们打开Jmeter的 选项-》勾选Log Viewer,查看Jmeter运行日志执行上面的beanshell源码得到
dayDate=2018-04-12 ,yearDate=2019-04-11 。
在beanshell中可以使用 log.info() 打印调试beanshell脚本的日志
四、beanshell脚本加解密
说到beanshell,不得不说一下我们使用beanshell脚本进行密码的加解密操作,因为出于安全的考虑,登录或支付时的密码都会有加解密操作,这里以加密为例:
首先需要开发同学帮忙,把加解的Java代码打成password.jar包(自己命名),然后在Jmeter的测试计划页面添加password.jar包,这样才能在beanshell中执行Java时import导入加密的Java类。如图:
Jar包的关键代码,调用FrameDemo.java
的generateKey方法:
比如我们想要把登录密码qq1111进行加密,并在Jmeter引用的步骤
1、 Jmeter添加jar包
2、 Beanshell中import导入FrameDemo.java
3、 调用FrameDemo.java的generateKey方法进行加密操作,generateKey有3个入参,前2个是加密的秘钥,第3个是待加密的密码,我们秘钥是固定的,待加密的密码是qq1111,我们可以把待加密的密码写死在beanshell中或者从Jmeter中传进去。然后我们会选择从Jmeter中传进去,这样灵活性更高。
4、 Beanshell把加密后的字符串传给Jmeter,供Jmeter引用。
BeanShell PreProcessor的Java源码:
//在测试计划页面先添加加密jar包import com.forth.FrameDemo;//加密log.info("*****加密*****"); //输出日志String password = vars.get("login_pw");//输入登录密码-这样写会取Jmeter变量login_pw的值log.info("jmeter-loginpw="+password);String password = "qq1111"; //输入登录密码String tpk = "30818902818100ccd601e07aeffc7f5f6d20d…";String kek = "308189028181009fa6334baf70c336163222…";String loginpw = FrameDemo.generateKey(tpk,kek,password); //调用工具类中的方法进行加密vars.put("loginpw",loginpw); //把值保存到jmeter变量loginpw中log.info("loginpw="+loginpw);
PS:
Beanshell内置对象vars对Jmeter变量进行存取操作
vars.get("login_pw") //从Jmeter中获取变量login_pw的值
vars.put("loginpw",loginpw); //把beanshell中loginpw的值存到Jmeter变量loginpw中
五、jmeter属性变量
我们在用Jmeter进行接口测试时,每个接口都需要输入IP和端口,如果我们在sampler中把IP和端口写死成172.20.128.188和8077。那么一旦我们的测试环境迁移,我们就需要对批量的脚本中的批量接口进行修改IP和端口,修改次数=脚本个数X脚本的接口数,那是一件很恐怖的事情,且没有技术含量。聪明的我们知道了,要先在Jmeter中把IP和端口定义好,那样修改量就会大大减少。如图:
但是这样我们IP和端口变了,我们还是得一个脚本一个脚本的打开进行修改,修改次数=脚本个数,还是有点麻烦。我们可以试着把Jmeter脚本中的IP和端口都引用同一个地方的同一个值,其实就是定义一个针对脚本的全局变量,那么jmeter属性变量了解一下,如图:
修改次数=1,嗯,完美
Jmeter的bin目录下jmeter.properties文件可以定义jmeter属性变量
打开jmeter.properties文件,插入两行
IP=172.20.128.188PORT=8077
Jmx脚本中引用:${__P(IP,)} ,${__P(PORT,)} ,修改jmeter.properties后,需重启jmeter生效。
bin下user.properties也可定义jmeter属性值,那么问题来了,user.properties和jmeter.properties同时定义PORT的值,一个是8077,一个是8078,最终${__P(PORT,)}
引用时值会是多少?好奇的朋友可以试一下然后留言答案,顺便探讨Jmeter的其它知识。Git还没弄好,弄好后把代码和相关脚本一起放过去。
感觉自己的排版和描述可以优化,特别是代码和英文的排版,希望有大佬看到可以提点一下,感谢阅读。
程序爬虫获取国内外测试资源分享给自学爱好者。
关注后回复测试资料,打包资料下载。
-The End-
mcfmcfmcf
(唯一联系方式)
△
加入微信群,交流更自然
﹍﹍﹍﹍﹍﹍﹍﹍﹍﹍﹍﹍﹍﹍﹍﹍﹍﹍﹍﹍
△
关注测试站
自学更简单
点击“阅读原文”关注头条号回复【资料】获取资源
以上是关于性能测试工具:jmeter 正则表达式,你可能只知其一的主要内容,如果未能解决你的问题,请参考以下文章