其实本来是要继续复习python面向对象部分的,但是今天工作闲暇刚好在挂接口测试的东西,闲着没事复习了一下postman的参数化然后觉得有点无聊就想起来jmeter里跨线程组好像也可以传参的,结果有点忘记了最便捷的跨线程传参方法,就记得一个BeanShell取样器提取全局变量,用另外一个前置处理器中的Beanshell调试了半天,感觉真是瞎折腾,这篇文章是翻阅了之前的demo然后顺便复习了jmeter的传参方法顺不下折腾快两小时没搞出来的气来更新的。
关联在这里可能对学过接口测试的人都比较熟悉,其实在之前基础接口测试里面的postman的学习里我也是用的关联来形容,因为接口之间是可以有很强的关联和依赖性的。还是以最基础的登录接口举例,我们最常见的就是在登录后把服务端给的token存储起来,然后在其他的接口例如查询接口当中进行我们新的接口请求就会用到token作为我们的新接口的请求头,因此关联依赖这个词就由此而来。
这里标题是Jmeter的关联,那么我们和postman不同的是我们postman用的最多的就是json格式数据的提取,jmeter里的主流提取方法根据提取器的不同有三种(当然还有很多种,其他使用的不这么多):正则表达式、xpath、json提取器。ps:postman也是可以使用这些的,不过jmeter作为工具用起来写的代码语言会少很多。
下面会先简单回顾一下之前三种方式的提取格式和步骤,不具体截图了。
首先说明,正则表达式可以提取任意格式的响应数据。那么什么是正则表达式,它是一个共识,或者说一套规则,使用这套规则,能够从任意字符串中提取出需要的数据内容。
常用的语法格式如下:
左边界(.*?)右边界
这里简单描述,"*"是通配符的意思,之前在数据库里也重点说过了,它是可以代表任意字符的意思,但是 除了回车和换行!! 这两个是有对应的转义字符的,学了语言 python当中也有提到过。
".*" 的意思是代表前面的字符出现0次或者多次,而.* 匹配规则,找到左边界值后,往右查找匹配右边界,中间的所有数据都会被记录下来。
"?" 在.*后面加上问号,代表非贪婪匹配,只会查找相同左边界和右边界范围内的东西输出。
一般来说正则表达式是在其他两个都实现不了的情况下才使用,大部分情况下的返回响应值都是json格式的数据,或者html可以用xpath定位,所以正则表达式用的也不多。
那么它引用的模板也很简单就是 $正则表达式值$如果在正则表达式里有多个提取值则可以是$2$$2$表示解析到的第几个值给title如$1$表示解析到的第几个值第一组值就是$1$。匹配数字 0就是随机取值,-1代表全部取值,1代表第一个值。
例如我们想要获取
021-1234-1234
022-1234-1235
023-1234-1236
那么我们在jmeter里的正则表达式提取器就该这么写:
因为重点不是讲传参,也不是拓展,如果对xpath感兴趣的可以自己去了解一下html语言。这里jmeter的xpath提取器主要是通过id定位,找html某个标签,可以通过// 带上标签名,这里的//其实就是相对位置了(有点类似linux里的绝对路径和相对路径)。
我们如果是想找html响应体里的数据,我们就可以定位它的具体标签,比如 //title[@id='kw']。这里[@属性='属性值']也是之后在ui自动化里经常会用到的东西。
这里就不多拓展了,xpath的提取器唯一要注意的就是Use Tidy,在处理HTML格式响应数据的时候必须要选中,如果是XML或者XHTML格式的话可以取消选中。
json提取器是我们用的最多的提取器,因为它简单也很好理解。在postman里我们有写过js的脚本 var jsonData = pm.response(),然后对token的提取就是 jsonData.data.token,因为它是有分机的,同样在jmeter里 一模一样的提取 我们就变成了 $.data.token,这样的形式就算是我们把它提取出来了。如下图所示,给它定义了一个引用它的命名“token”。
直接以最简单最常用的json提取器来举例,我们现在已经拿到了我们想要的token变量了,那么我们怎么来调用它呢?假设,我们现在是在同一个线程组里,也就是模拟成同一个用户对它操作,我们可以直接在该线程组底下的http信息头管理器里添加我们想要的请求头和对应的数据,例如
那么这时候我们就实现了我们的参数传递,在一个线程组里完成了我们的依赖如下图
ps:这里是Beanshell取样器,文末结尾也有截图!
从上面我们也知道了在同一个线程组里的三种方式传参完成关联,那么如果在不同线程组里的两个相关联的接口怎么实现穿参呢?
这时候需要我们引入一个概念,叫做jmeter属性。我们知道property这个单词的翻译就有属性的意思,但是我们还有个更熟悉的词汇叫做“全局变量”。这里我们就可以把它理解成,我们将提取到的token放到这个全局变量的容器当中,在其他线程组(其他用户)需要进行提取的时候把它拿出来。
ps:在postman当中我们是用了js的语句将pm.globals.set("glb_token",token)来设置全局变量,在jmeter当中则不需要这么麻烦。博客上有很多人都是用的代码语言来在BeanShell提取器里一顿操作,jmeter这么好的工具怎么会舍得让我们使用者敲代码呢。
我们能看到jmeter里选项-函数助手对话框(快捷键ctrl+shift+f1),在下拉函数列表中找到这个函数。它的概念是什么呢?它就是将值存储为我们jmeter属性的,也就是作为全局变量。
那么通过下面的这个框,我们就能将我们先前的提取到的token值存储到全局变量当中去。
在点击生成之后,我们看到了我们想要的具体的函数字符串在上图当中,我们来解析一下其他的属性名称字段。首先“属性名称” 是你自己定义的这个jmeter属性(全局变量)的名称,底下的属性的值可不是直接填写token,而是你之前通过json提取器命名后的,能够调用它的值,因此这里是一个jmeter里调用的格式${调用变量}。
到此我们知道了我们像postman那样知道了全局变量的概念,那么我们该怎么设置全局变量并且提取它呢。
刚刚我们得到了那个函数,它是设置我们的jmeter属性(全局变量),我们先不管BeanShell取样器的原理是怎么样的,它是放在【取样器】中的,在这里可以理解为通过对提取到的函数进行代码脚本的执行。我们用的那个函数就需要把它放到这个取样器当中,如下图:
如下图所示,我们在设置完成了set_property,jmeter属性函数之后我们也有对应的jmeter属性读取的函数,这里很大方便我们去在BeanShell写逻辑语句的繁琐。
这里我们得到了_property函数语句,我们就可以直接拿到我们熟悉的http信息头管理器。当然这个信息头管理器是要在新的线程组里建的,然后我们再把函数引用写入到请求头当中,这样我们就开始运行了。不过我们要注意一点,因为我们是先进行token导入全局变量的操作,有先后顺序的话我们就应该在测试计划当中把每个线程设置成独立有顺序的执行:
最后实现的元件、取样器、监听器如下图所示:
巧用jmeter里的插件和函数调用,能够替代很多的脚本编写,同样可视化的性能测试也是通过丰富的插件实现的,因此jmeter工具非常值得去深入探究。化繁为简才是最高效的,当然在理解的前提上“偷懒”是最可取的。