前言
在之前的博文“JMeter案例优化:测试执行结束后,实现tearDown的几种方式”中,尝试了JMeter的循环控制器While Controller,发现还有点小复杂,将学习过程记录下来,免得遗忘。
注:我使用的是JMeter 5.5
添加While Controller
右击需要添加While Controller的线程组,选择Add->Logic Controller->While Controller
添加成功后,界面如下:
最重要的,就是Condition这个文本框了,循环条件。
循环条件
While Controller的循环条件有三种可能值:空,LAST和表达式,下面将一一举例说明。
1、空:
条件为空时,本循环体中最后一个采样器执行失败时退出。
1.1 循环体内最后一个采样器执行失败的情形
1.1.1 While Controller中添加两个Dummy Sampler,分别命名为11和22
1.1.2 改写22的Response Data,响应中的result字段为1-10的随机数
{"result": "${__Random(1,10,)}"}
1.1.3 22添加JSON Assertion:result <= 7。则当result>7时,断言失败,构造出本采样器失败的情形。
^[0-7]?$
1.1.4 循环提外添加一个Dummy Sampler,当循环结束后,执行本采样器。
构造完毕,执行一次:
当采样器22的响应为8时,断言失败,循环体内最后一个采样器的执行结果为fail,满足循环结束条件,循环结束。
1.2 循环体内非最后一个采样器执行失败的情形(第一个采样器失败)
将上例中的11 和 22调换位置,22作为循环体内的第一个采样器,重新执行
可以看到,虽然22已经断言失败了,但是循环继续。因为循环条件仅判断循环体内最后一个采样器的结果。
2、LAST
值为LAST时,有两个条件
1、循环进入条件:若循环体前面的最后一个采样器失败,不进入循环。
2、循环退出条件:当循环体内的最后一个采样器失败时退出;
第2条,与表达式为空时一样。所以我们着重看第一个条件。
2.1 循环体前面的最后一个采样器成功,进入循环
我们将之前的While Controller复制一份,稍加改造
2.1.1 while Controller表达式改为LAST
2.1.2 循环体内仍然是最后一个采样器可能出现失败的情况
2.1.3 循环外的采样器放到循环体前面去,以便构造循环体前面的最后一个采样器成功的情形
2.1.4 循环外的采样器Response Data 修改为
{"result": true}
2.1.5 循环外的采样器添加JSON Assertion:
这样,这个采样器将断言成功,
执行一下
可见,因循环体前面的最后一个采样器执行成功,成功进入循环;
并在循环体内的最后一个采样器执行失败时,退出循环。
2.2 循环体前面的最后一个采样器失败,不进入循环
修改循环外的采样器的Response Data为:
{"result": false}
这样断言将失败,不会进入循环:
3、循环条件为变量、属性或函数,将一直循环,直到循环条件变成false
3.1 变量、属性
以变量为例,同样,将前面的While Controller复制一份,稍加改造
3.1.1 11的Response Data 修改为
{"result": false}
3.1.2 11添加JSON Extractor
3.1.2 While Controller的Condition修改为${result}
执行结果:
1、进入循环,顺序执行11和22采样器
2、再次判断:11采样器的响应result为false,即所获取的变量${result}为false,满足循环退出条件,于是循环结束,没有执行第二轮。
3.2 函数
可以是__jexl3或__groovy函数。当函数的结果为false是,结束循环
比如JMeter案例优化:测试执行结束后,实现tearDown的几种方式中的例子:
${__jexl3(${__time(,)}-${__P(TESTSTART.MS,)}<=10000)}
当执行时间<=10秒时为true,继续循环;
当执行时间>10秒时为false,结束循环 。
Tip:循环次数:
JMeter提供了一个变量__jm__<Name of your element>__idx来统计循环次数,比如下图,循环控制器组件的名称是While Controller-var,便可以通过${__jm__While Controller-var__idx}来获取循环次数
从0开始计数:
不过这个变量作用域仅限于循环体内,出了循环体就不能用了。目前还没想到什么应用场景。
附:__jexl3常用语法总结
${__jexl3(${__Random(0,50,)}==0,)} //数字等于
${__jexl3(${__Random(0,50,)}!=0,)} //数字不等于
${__jexl3("${var}".equals("qwe"),)} //字符串相等
${__jexl3("${var}" eq "qwe",)}
${__jexl3("${var}" == "qwe",)}
${__jexl3(!"${var}".equals("q1we"),)} //字符串不相等
${__jexl3("${var}" ne "qwe1",)}
${__jexl3("${var}" != "qwe",)}
${__jexl3("${var}}".contains("pre"),)} //字符串包含
${__jexl3(!"${var}".contains("pre"),)} //字符串不包含
${__jexl3("${var}".size() < 3,)} //字符串长度,可以用size()或者length(),效果一样
${__jexl3("${var}".size() > 3,)}
${__jexl3("${var}".size() == 3,)}
${__jexl3("${var}".empty(),re)} //字符串为空
${__jexl3(${__Random(0,50,)}==0 || "${var}".contains("pre"),)} //组合条件zhozho