08、JMeter 教程 - JMeter逻辑控制器上

1.简介

Jmeter官网对逻辑控制器的解释是:“Logic Controllers determine the order in which Samplers are processed.”。

意思是说,逻辑控制器可以控制采样器(samplers)的执行顺序。由此可知,控制器需要和采样器一起使用,否则控制器就没有什么意义了。放在控制器下面的所有的采样器都会当做一个整体,执行时也会一起被执行。

JMeter逻辑控制器可以对元件的执行逻辑进行控制,除仅一次控制器外,其他可以嵌套别的种类的逻辑控制器。

2.逻辑控制器分类

JMeter中的Logic Controller分为两类:

(1)控制测试计划执行过程中节点的逻辑执行顺序,如:Loop Controller、If Controller等;

(2)对测试计划中的脚本进行分组、方便JMeter统计执行结果以及进行脚本的运行时控制等,如:Throughput Controller、Transaction Controller。

3.预览逻辑控制器家族

首先我们来看一下JMeter的逻辑控制器,路径:线程组(用户)->添加->逻辑控制器(Logic Controller);我们可以清楚地看到JMeter5中共有17个逻辑控制器,如下图所示:

 

4.常用逻辑控制器详解

4.1 if Controller

在实际工作中,当使用Jmeter进行接口测试或者性能测试时,有时需要根据不同条件做不同的操作,为了解决这个问题,Jmeter提供了IF控制器。顾名思义,IF控制器实现了代码中IF的功能,通过判断表达式的True/False来判定是否执行相应的操作。通过条件判断下边的节点执行不执行。

4、 1.1新建:线程组>添加>逻辑控制器>如果(if)控制器,如下图所示:;

 

4、 1.2关键参数说明如下:;

Name:名称,可以随意设置,甚至为空;

Comments:注释,可随意设置,可以为空。

Expression (must evaluate to true or false) :表达式(值必须是true或false),也就是说,在右边文本框中输入的条件值必须是true 或 false,(默认情况下)

Interpret Condition as Variable Expression?:默认勾选项,将条件解释为变量表达式(需要使用__jexl3 or __groovy 表达式)

Evaluate for all children?:条件作用于每个子项(具体理解会在后边实战篇列举例子说明),判断条件是否针对所有子节点,默认不勾选,只在if Controller的入口处判断一次。

注意:敲黑板!!!敲脑壳啦!!!

  • 文本框上的黄色感叹号,就是提示你,建议采用__jexl3 or __groovy 表达式,以提高性能,也就是默认的方式。
  • if 控制器 只能作用于其下的子项

4、 1.3默认用法;

  • 默认用法,就是采用__jexl3 or __groovy 表达式if 控制器下有一个 访问csdn首页的取样器,只有if条件满足时,才会执行该取样器。采用默认方式,将条件'迪丽热巴'=='迪丽热巴',放入 __jexl3表达式中。如下图所示:

 

  • 如果不知道表达式如何使用,可使用Jmeter 的函数助手,函数助手图标 > 选择_jexl3 > 在值的输入框输入'白日梦想家-曼曼'=='白日梦想家-曼曼' > 点击‘生成’ > 全选Ctrl+C复制 > Ctrl+V粘贴到表达式处 如下图所示:

 

3、 配置好以后,运行JMeter,选择HTML,然后查看结果树,如下图所示:;

 

直接输入条件

1、 直接输入只需要去掉“InterpretConditionasVariableExpression?”前面复选框,直接输入条件:''==''取样器将被执行如下图所示:;

 

2、 配置好以后,运行JMeter,选择HTML,然后查看结果树,如下图所示:;

 

4、 1.4条件中使用变量;

我们在日常工作中在很多的测试场景下,需要根据用户变量或者上一个取样器的返回值来进行条件判断,从而决定是否需要执行某一个的取样器。

1、 首先我们新增一个用户变量用户变量及配置,如下图所示:;

 

2、 IFController及配置如下图所示:;

 

 

 

4.2 Transaction Controller

  事务响应时间是我们衡量业务性能的主要指标,事务控制器可以把其他节点下的取样器执行消耗时间累加在一起,便于统计。同时对每一个取样器的执行时间进行统计。   如果事务控制器下的取样器有多个,只有当所有的取样器都运行成功,整个事务控制器定义的事物才算成功。   用于将Test Plan中的特定部分组织成一个Transaction,JMeter中Transaction的作用在于,可以针对Transaction统计其响应时间、吞吐量等。比如说,一个用户操作可能需要多个Sampler来模拟,此时使用Transaction Controller,可以更准确地得到该用户操作的性能指标,如响应时间等。这个时间包含该控制器范围内的所有处理时间,而不仅仅是采样器的。

这个就非常有用了。我们前面有提到过事务的概念,有时候我们不关心单个请求的响应时间,而是关心一组相关请求的整体响应时间,怎么来统计呢?就需要借助事务这个概念,把这组请求,放到一个事务控制器下面。

4、 2.1新建:线程组>添加>逻辑控制器>事务控制器,如下图所示:;

 

4、 2.2关键参数说明如下:;

Name:名称,可以随意设置,甚至为空;

Comments:注释,可随意设置,可以为空;

generate parent sample:选择是否生成一个父取样器;

include duration of timer and pre-post processors in generated samle:是否包含定时器,选择将在取样器前与后加上延时。(建议不要勾选,否则统计就比较麻烦了,还需要你扣除延时)

4、 2.3generateparentsample用法;

  • 列举一个测试场景:这两个请求的单个请求的响应时间,那么就来看看如下实例。

单个请求,那么不勾选generate parent sample

运行JMeter,查看聚合报告的单个请求的响应时间,如下图所示:

 

  • 列举一个测试场景:我们需要了解 csdn首页 访问我的首页这两个请求作为一组请求的响应时间,那么就来看看如下实例。

一组请求,那么勾选generate parent sample

运行JMeter,查看聚合报告的一组请求的响应时间,如下图所示:

 

4.3 Loop Controller

循环控制器可以控制在其节点下的元件的执行次数,可以是具体数字,也可以是变量。

4、 3.1默认循环一次新建:线程组>添加>逻辑控制器>循环控制器,如下图所示:;

 

4、 3.2关键参数说明如下:;

Name:名称,可以随意设置,甚至为空;

Comments:注释,可随意设置,可以为空;

Forever:勾选上这一项表示一直循环下去。

注意:敲黑板,敲脑壳!!!

如果同时设置了线程组的循环次数和循环控制器的循环次数,那循环控制器的子节点运行的次数为两个数值相乘的结果。

4、 3.3ThreadGroup和循环控制器的区别;

准备两个请求,设置线程组1个线程,5次loop,下边有一个请求:访问我的首页 一个Loop Controller(设置2次loop),下边有一个请求:访问csdn首页

  • 线程组,如下图所示:

 

  • 循环控制器,如下图所示:

 

运行JMeter,查看结果树,为了清楚地看出结果,将第一个请求故意配置成失败的;如下图所示:

 

从上边的结果可以看出:

(1)如果同时设置了线程组的循环次数和循环控制器的循环次数,那循环控制器的子节点运行的次数为两个数值相乘的结果。

(2)运行顺序是:先执行线程组里的循环,再执行循环控制器里的循环。

4.4 While Controller

While条件控制器,其节点下的元件将一直运行直到While 条件为false。

4、 4.1新建:线程组>添加>逻辑控制器>While控制器,如下图所示:;

 

4、 4.2关键参数说明如下:;

Name:名称,可以随意设置,甚至为空;

Comments:注释,可随意设置,可以为空;

Condition:接受变量表达式与变量。条件为 Flase 的时候,才会跳出 While 循环,否则一直执行 While 控制器下的元件。

4、 4.3While控制器提供三个常量;

  • Blank:当循环中最后一个取样器失败后停止
  • LAST:当循换前有取样器失败,不进入循环
  • Otherwise:当判断条件为false时,停止循环

4、 4.4Blank;

不填(空):当 While 控制器下最后一个样例执行失败后 跳出循环

运行JMeter,查看结果树,(你可以通过鼠标拖动最后失败的取样器,移动到第一个或者第二个位置的时候,运行JMeter后,会发现在一直运行);如下图所示:

 

 

4、 4.5LAST;

LAST :当 While 控制器下最后一个样例执行失败后 跳出循环,如果 While 控制器 前一个样例执行失败,则不会进入While循环,也就是不会执行While控制器下的样例。

1、 取样器树还是上边的位置和顺序这次我们在While控制器表达式处填写:LAST,如下图所示:;

 

2、 运行JMeter,查看结果树,(你可以通过鼠标拖动最后失败的取样器,移动到第一个或者第二个位置的时候,运行JMeter后,会发现在一直运行);细心的你可以发现循环只跑一遍,与不填的结果是一样的如下图所示:;

 

3、 但是输入LAST的时候,还会出现一个结果,那就是:如果While控制器的前一个样例执行失败,则不会进入While控制器;

在While 控制器 前面 添加两个取样器:取样器1 访问百度,取样器2 访问http 使取样器2 访问http 执行失败。取样器2必须在While控制器前边且执行失败。

1、 运行JMeter,查看结果树,执行结果发现,取样器1、取样器2执行了,但没有进入While控制器,如下图所示:;

 

4、 4.6Otherwise;

自定义条件:值为True 或 False的函数/变量/属性 表达式;类似前边讲解的IF控制器

1、 用户自定义变量,变量名:北京宏哥,变量值:true,如下图所示:;

 

2、 While控制器配置,取到变量的值:${kk的kk},填写到表达式的地方,如下图所示:;

 

JMeter执行过程的逻辑分析:

  • kk的kk(线程组)下 有 1 个用户自定义变量,变量kk的kk 的值为 true,While控制器的条件为:${kk的kk} 取到的值始终是 true。
  • 所以一旦开始执行始终满足条件,那么按理说就应该一直执行 访问csdn首页 、访问kk的kk的首页、百度3个取样器,

3、 运行JMeter,查看结果树,(运行JMeter后,会发现在一直运行),对比一下,如下图所示:;

 

4.5 ForEach Controller

ForEach 控制器:一般搭配用户变量使用。依次调用用户定义的变量,直到最后一个,结束循环。为了满足ForEach Controller提取数据,变量命名的格式一般为“变量名_数字”,其中数字从1开始。

  • 即遍历循环控制器,顾名思义是定义一个循环规则。
  • 用来遍历当前元素的所有可执行场景。
  • 在用户自定义变量中读取一系列相关的变量,该控制器下的采样器或控制器都会被执行一次或多次,每次读取不同的变量值。
  • 这个控制器一般配合配置元件 → 正则表达式提取器来一起使用,可对页面上的某些元素进行重复处理。

4、 5.1新建:线程组>添加>逻辑控制器>ForEach控制器,如下图所示:;

 

4、 5.2关键参数说明如下:;

Name:名称,可以随意设置,甚至为空;

Comments:注释,可随意设置,可以为空;

Input variable prefix:输入变量前缀;可以在“用户自定义变量”中定义一组变量,循环控制器可以从中获取到变量对应的值,然后作为循环控制器的循环条件,还可以输出变量作为取样器的参数。

Start index for loop:循环变量下标起点;循环指数开始(唯一)→ 遍历查询的变量范围,开始的值(这里如果不填写,默认从 1 开始,如果没有 1 开始的变量,执行时会报错)

Endindex for loop:循环变量下标终点;循环指数结束(包含)→ 遍历查询的变量范围,结束的值

Output variable name:输出变量名称;循环控制器生成的变量名称。后续可通过${}引用

Add"_" before number ?: 数字之前是否加“_”;如果定义的变量名中有下划线的话就要勾选此项,否则找不到;反之,没有的话不要勾选,否则同样找不到变量

4、 5.3实例讲解;

1、 首先在自定义5个前缀为小羊kerry的变量,值分别为abcde并且小羊kerry后面的数字是连续的,如果不连续,则不会被循环到,如下图所示:;

 

2、 配置ForEach控制器,如下图所示:![ ][nbsp29];

3、 添加请求访问csdn首页+输出值:${小羊},输出值是在控制器的输出变量小羊,通过${小羊}取到输出变量的值,如下图所示:;

 

4、 添加查看结果树,运行JMeter,查看结果树,如下图所示:;

 

注意:敲黑板,敲脑袋!!!

1、 输入变量的后缀数值一定要连续,比如小羊kerry_1,小羊kerry_2,小羊kerry_3...这样,如果中间有不连续的,循环会中断;

2、 循环开始的设定:如果变量为小羊kerry_1,小羊kerry_2,小羊kerry_3,而设定的开始为1,则会从小羊kerry_2开始循环;

3、 循环结束的设定:如果变量有3个小羊kerry_1,小羊kerry_2,小羊kerry_3,而设定的结束为5,则只会循环小羊kerry_1,小羊kerry_2,小羊kerry_3,如果设定的结束为2,则会循环小羊kerry_1,小羊kerry_2;