zoukankan      html  css  js  c++  java
  • Jmeter(二十三)

    -------------------------------------------------------------------

    转载自:北京-宏哥

    https://www.cnblogs.com/du-hong/p/13366105.html

    --------------------------------------------------------------------

    1.简介

      在性能测试中为了真实模拟用户请求,往往我们需要让提交的表单内容每次都发生变化,这个过程叫做参数化。JMeter配置元件与前置处理器都能帮助我们进行参数化,但是都有局限性,为了帮助我们能够更好地进行参数化,JMeter提供了一组函数来帮助我们参数化生成需要的数据,这些函数可以函数助手面板来进行编辑。当然函数助手的功能不仅仅是做参数化,还能帮助我们运算、字符编码格式转换、获取运行时参数等功能。下面宏哥介绍和分享一下函数助手中的函数。

    JMeter提供了很多函数,如果能够熟练使用,可以为脚本带来很多方便。可以很方便的实现一些小功能,几乎可以用于测试计划中的任何元件。

    JMeter函数是一种特殊值,可用于除测试计划外的任何组件。

    函数调用的格式如下所示:

    ${__functionName(var1,var2,var3)}

    其中,“__”是两个英文半角的下划线,functionName为函数名,括号内是函数的参数,无参数时可以不用括号,如${__UUID},其中参数视不同函数而定。

    Tips:

    如果参数包含逗号,那么一定要使用“”来转义,否则JMeter会把它当作一个参数分隔符

    实际使用时,可通过函数助手对话框选择函数,设置参数后,点击生成按钮生成函数字符串。 

    2.JMeter 中的常用函数主要分为如下几类

    函数类型函数名称函数作用启用版本
    脚本函数  __BeanShell 执行 beanshell 脚本 1.X
    __javaScript 执行 js 脚本 1.9
    字符串操作函数   __split 根据分隔符拆分字符串为多个变量 2.0.2
    __changeCase 转换大小写 4.0
    __regexFunction 使用正则表达式解析之前的响应结果 1.X
    属性信息函数    __isPropDefined 判断属性是否存在 4.0
    __property 对多个整数求和 1.8.1
    __P 简化的属性函数,用于与命令行上定义的属性一起使用 2.0
    __setProperty 简化的属性函数,用于与命令行上定义的属性一起使用 2.0
    数据输入函数    __StringFromFile 从文本文件中读取字符串,每次调用读取一行 1.9
    __FileToString 把文件读取成一个字符串,每次调用都是读取整个文件 2.4
    __CSVRead 返回当前正在执行的线程的编号 1.9
    __XPath 使用 XPath 语法匹配 XML文件 2.0
    数据计算函数       __counter 计数器函数 1.9
    __intSum 对多个整数求和 1.8.1
    __longSum 长整型求和 2.3.2
    __Random 返回指定最大值和最小值之间的随机整数 1.9
    __RandomDate 返回给定开始日期和结束日期值之间的随机日期 3.3
    _RandomString 根据给定的字符生成指定长度的随机字符串 2.6
    __UUID 通用唯一标识符函数 2.9
    获取信息函数      __TestPlanName 返回当前测试计划的名称  
    __threadGroupName 返回当前线程组的名称 4.1
    __threadNum 返回当前正在执行的线程的编号 1.X
    __samplerName 返回当前请求的名称 2.5
    __log 输出日志信息 2.2
    __time 以多种格式返回当前时间 2.2

    2.1 脚本函数 

    2.1.1__BeanShell函数

    JMeter支持BeanShell脚本语言,JMeter函数助手中提供BeanShell函数支持,__BeanShell函数入参可以是BeanShell语法的程序语句或者BeanShell脚本文件。调出函数面板,我们在“值”中输入的是两个字符串相加,然后点击“生成”按钮,就会生成一串以$开头的表达式,表达式在请求(Sampler)中可以直接调用。

    1、我们先来看看这个__BeanShell 长得是啥样子,路径:函数助手 > 选择__BeanShell ,如下图所示:

    2、关键参数说明:

    它有两个参数,第一个参数是要执行的语句,可以是beanshell语句或者是文件地址,是必选参数;第二个参数是保存结果的变量名称,非必选参数。

    3、实例

    1.${__BeanShell(123456*789)}:返回97406784,如下图所示:

    2.${__BeanShell(source("function.bsh"))}:会执行外部脚本function.bsh,并返回结果,如下图所示:

    文件里代码:System.out.print("bjhg");

     返回结果:

    3.${__BeanShell(import java.util.*;Properties props = System.getProperties();String osName  = props.getProperty("os.name");if(osName.contains("Windows"))return 443;return 8443;)}:判断Windows返回端口443

    import java.util.*;
    Properties props = System.getProperties();
    String osName  = props.getProperty("os.name");
    if(osName.contains("Windows"))
        return 443;
    return 8443;

    4、与beanshell元件比较:

    该函数与beanshell元件(beanshell sampler、beanshell preprocess等)作用是一样的,只是beanshell函数更常用于一些简单的判断或计算等,可以把少量的脚本放在函数中直接赋值给一个变量,而不用总是添加beanshell元件。

    2.1.2__javaScript

    用来执行 JavaScript 脚本片段,并返回结果值。

    该函数会调用标准的 JavaScript 解释器,还可以直接调用 jmeter 的内置函数。

    注意:文本字符串要添加必要的引号。如果表达式中有逗号,要确保对其转义。

    例如:${__javaScript('${sp}'.slice(7\,99999))},对 7 之后的逗号进行了转义。

    1、我们先来看看这个__javaScript长得是啥样子,路径:函数助手 > 选择__javaScript,如下图所示:

    2、关键参数说明:

    第一个参数:JavaScript代码片段,待执行的JavaScript代码片段。例如:

    1.new Date():返回当前日期和时间

    2. Math.floor(Math.random()*(${maxRandom},+1)):在0 和变量maxRandom之间的随机数

    3.${minRandom}+Math.floor(Math.random()*(${maxRandom}-${minRandom}+1)):在变量 minRandom和maxRandom之间的随机数"${VAR}"=="abcd"

    第二个参数:变量名,重用函数计算值的引用名

    请记得为文本字符串添加必要的引号。另外,如果表达式中有逗号,请确保对其转义。例如,${__javaScript('${sp}'.slice(7\,99999))},对7之后的逗号进行了转义。

    3、实例

    2.2字符串操作函数

    2.2.1__split

    根据分隔符拆分字符串为多个变量。

    当两个分隔符中间没有字符时,返回 ?

    被拆分出来的字符串,保存在变量中,类似这样:${VAR_1}, ${VAR_2} ...,总个数是 ${VAR_n}

    如果最后一个字符是分隔符,也会返回 ?

    函数__split会通过分隔符来拆分传递给它的字符串,并返回原始的字符串。如果分隔符紧挨在一起,那么函数就会以变量值的形式返回"?"。

    拆分出来的字符串,以变量${VAR_1}、{VAR_2}…以此类推的形式加以返回。JMeter 2.1.2及其以后版本,拖尾的分隔符会被认为缺少一个变量,会返回"?"。

    另外,为了更好地配合ForEach控制器,现在__split会删除第一个不用的变量(由前一次分隔符所设置)。

    1、我们先来看看这个__split长得是啥样子,路径:函数助手 > 选择__split,如下图所示:

    2、关键参数说明:

    待拆分字符串

    一个待拆分字符串,例如“a|b|c”

    变量名

    重用函数计算值的引用名

    分隔符

    分隔符,例如“|”。如果省略了此参数,函数会使用逗号做分隔符。需要注意的是,假如

    要多此一举,明确指定使用逗号,需要对逗号转义,如“\,”

    3、示例:

    定义字符串:
    VAR="a||c|"
    
    调用 split 函数:
    ${__split(${VAR},VAR,|)}
    返回 "a||c|",并生成如下变量:
    VAR_n=4 
    VAR_1=a 
    VAR_2=? 
    VAR_3=c 
    VAR_4=? 
    VAR_5=null

    2.2.2__changeCase

    根据指定的模式,修改字符串大小写;

    可选模式有:UPPERLOWERCAPITALIZE

    1、我们先来看看这个__changeCase长得是啥样子,路径:函数助手 > 选择__changeCase,如下图所示:

    2、关键参数说明: 

    第一个参数:需要修改的字符串

    第二个参数:对字符串作用的模式3种

    第三个参数:字符串修改后,存储的变量名,赋值的变量名

    3、示例:

    (1)UPPER--转换成大写字母: ${__changeCase(Avaro omnia desunt\, inopi pauca\, sapienti nihil,UPPER,)} 返回 AVARO OMNIA DESUNT, INOPI PAUCA, SAPIENTI NIHIL

    (2)LOWER--转换成小写字母: ${__changeCase(LABOR OMNIA VINCIT IMPROBUS,LOWER,)} 返回 labor omnia vincit improbus

    (3)CAPITALIZE--单词首字母大写: ${__changeCase(omnibus viis romam pervenitur,CAPITALIZE,)} 返回 Omnibus viis romam pervenitur

    2.2.3__regexFunction

    使用正则表达式解析之前的响应结果。

    1、我们先来看看这个__regexFunction长得是啥样子,路径:函数助手 > 选择__regexFunction,如下图所示:

    该函数使用用户提供的正则表达式来解析前面的服务器响应(或者是某个变量值)。函数会返回一个有模板的字符串,其中携带有可变的值。

    在函数的第6个参数中,可以指定一个引用名,保存变量值,供后续调用。__regexFunction还可以被用来保存值,以便供后续使用。在函数的第6个参数中,测试人员可以指定一个引用名。在函数执行以后,测试人员可以使用用户定义值的语法来获取同样的值。例如,如果测试人员输入"refName"作为第6个参数,那么测试人员可以使用

    变量调用示例:

    Name of variable in which to store the result:在这个参数中设置变量名为 refName ,那么我们可以使用:

    ${refName}来引用第2个参数(Template for the replacement string)的计算结果,这依赖于函数的解析结果。

    ${refName_g0}来引用函数解析后发现的所有匹配结果。

    ${refName_g1}来引用函数解析后发现的第一个匹配组合。

    ${refName_g#}来引用函数解析后发现的第n个匹配组合。

    ${refName_matchNr}来引用函数总共发现的匹配组合数目。

    2、具体参数描述如下:

    函数参数

    描述

    是否必需

    第1个参数

    第1个参数是用于解析服务器响应数据的正则表达式,它会找到所有匹配项;如果希望将表达式中的

    某部分应用在模板字符串中,一定记得为其加上圆括号。例如,<a href="(.*)">,这样就会将链

    接的值存放到第一个匹配组合中(这里只有一个匹配组合)。又如,<input type="hidden"

    name="(.*)"value="(.*)">,在这个例子中,链接的name作为第一个匹配组合,链接的value会

    作为第二个匹配组合,这些组合可以用在测试人员的模板字符串中。

    第2个参数

    这是一个模板字符串,函数会动态填写字符串的部分内容。要在字符串中引用正则表达式捕获的匹配组

    合,请使用语法:[groupnumber][groupnumber]。例如11或者 22,模板可以是任何字符串。

    第3个参数

    第3个参数告诉JMeter使用第几次匹配;测试人员的正则表达式可能会找到多个匹配项,对此,

    有4种选择:

    n     整数,直接告诉JMeter使用第几个匹配项;

    n     “1”对应第一个匹配,“2”对应第二个匹配,以此类推;

    n     RAND,告诉JMeter随机选择一个匹配项;

    n     ALL,告诉JMeter使用所有匹配项,为每个匹配项创建一个模板字符串,并将它们连接在一起

    n     浮点值0到1之间,根据公式(找到的总匹配数目*指定浮点值)计算使用第几个匹配项,计算值

          向最近的整数取整

    否,默认值为1

    第4个参数

    如果在上一个参数中选择了“ALL”,那么这第4个参数会被插入到重复的模板值之间

    第5个参数

    如果没有找到匹配项返回的默认值

    第6个参数

    重用函数解析值的引用名,参见上面内容

    第7个参数

    输入变量名称。如果指定了这一参数,那么该变量的值就会作为函数的输入,而不再使用前面的采样结

    果作为搜索对象


    其实这个函数的作用跟正则表达式提取器的作用是类似的。

    2.3属性信息函数

    2.3.1__isPropDefined

    用于判断属性是否存在。

    1、我们先来看看这个__isPropDefined长得是啥样子,路径:函数助手 > 选择__isPropDefined,如下图所示:

    2、关键参数说明:

     Name of property:属性名称

    3、示例:

    ${__isPropDefined(START.HMS)}
    判断属性 START.HMS 是否存在,返回 true。
    

    2.3.2__property

    获取属性值。获取Jmeter的属性,%JMETER_HOME%injmeter.properties

    1、我们先来看看这个__property长得是啥样子,路径:函数助手 > 选择__property,如下图所示:

    2、关键参数说明:

    Name of property:属性名称;

    Name of variable in which to store the result (optional):变量名;

    default Value:默认值

    3、示例:

    ${__property(user.dir)}  返回 user.dir 的值。
    ${__property(user.dir,UDIR)}   返回 user.dir 的值,并保存在变量 UDIR 中。
    
    ${__property(abcd,ABCD,atod)}   返回属性 abcd 的值,如果该属性未定义则返回 atod,并保存在变量 ABCD 中。
    ${__property(abcd,,atod)}    返回属性 abcd 的值,如果该属性未定义则返回 atod,不保存结果值。
    ${__property(log_level.jmeter,log_Level,)}

    2.3.3__P

    这是一个简化的属性函数,用于与命令行上定义的属性一起使用。获取命令行中定义的属性,非GUI方式运行测试计划时这个函数可用来做参数化,由运行命令动态指定参数值,方便与Jenkins等集成完成性能测试工作

    _property 函数不同,没有选项可以将值保存在变量中,如果不提供默认值,则假定为1。

    1、我们先来看看这个__P长得是啥样子,路径:函数助手 > 选择__P,如下图所示:

    2、关键参数说明:

    Name of property:属性名称;

    default Value:默认值

    3、示例:

    在脚本中定义如下两个函数:
    ${__P(group1.threads, 10)}
    ${__P(group1.loops)}
    
    在命令行中调用:
    jmeter -Jgroup1.threads=50  -Jgroup1.loops=100   执行时,两个参数分别是 50、100。
    
    若命令行中不设置属性,执行时,两个参数分别是 10、1。

    2.3.4__setProperty

    该函数用于设置 JMeter 属性的值。

    函数的默认返回值是空字符串,因此该函数可以被用在任何地方,只要对函数本身调用是正确的。

    1、我们先来看看这个__setProperty长得是啥样子,路径:函数助手 > 选择__setProperty,如下图所示:

    通过将函数可选的第3个参数设置为"true",函数就会返回属性的原始值。

    属性对于JMeter是全局的,因此可以被用来在线程和线程组之间通信。

    2、关键参数说明:

    Name of property:属性名称;

    Value of property:属性值;

    Return Original Value of property (default false)?:是否返回函数结果

    3、实例

    ${__setProperty(log_level.jmeter,Debug,true)}

    2.4数据输入函数

    2.4.2__StringFromFile

    从文件中读取内容,一行一行的读取,读完再从头开始。

    1、我们先来看看这个__StringFromFile长得是啥样子,路径:函数助手 > 选择__StringFromFile,如下图所示:

    作用

    用于从文本文件中读取字符串,每次读取一行,支持读取多个文件。

    使用配置元件CSV Data Set Config ,也能达到相同的目的,而且方法更简单,但是它目前不支持多个输入文件。

    每次调用函数,都会从文件中读取下一行。当到达文件末尾时,函数又会从文件开始处重新读取,直到最大循环次数。如果在一个测试脚本中对该函数有多次引用,那么每一次引用都会独立打开文件,即使文件名是相同的(如果函数读取的值,在脚本其他地方也有使用,那么就需要为每一次函数调用指定不同的变量名)。

    如果在打开或者读取文件时发生错误,那么函数就会返回字符串 **ERR**

    2、 参数

    参数描述是否必填
    文件名 文件名的路径 (路径可以相对于 JMeter 启动目录)。
    如果使用序列号,路径名称应该适合传递到 DecimalFormat。
    变量名 用于后续调用该函数的变量名称
    启动序号 初始序列号(如果省略,则将结束序列号视为循环计数)
    末端序号 最终序列号(如果省略,序列号可以无限制地增加)

    启动序号:初始的序列号,如果省略,那么结束序列号就代表文件的循环读取次数。

    末端序号:结束序列号,如果省略,那么序列号会无限增长。

     3、示例

    读取单个文件:
    ${_StringFromFile(test.txt,,,)}    读取test.txt
    
    读取多个文件,需要在文件名中使用序列号:
    ${_StringFromFile(PIN.DAT,,,2)}    读取 PIN.DAT 两次
    ${_StringFromFile(PIN#'.'DAT,,1,3)}    读取 PIN1.DAT PIN2.DAT PIN3.DAT
    ${_StringFromFile(pin000'.'dat,,6,8)}    读取 pin006.dat pin007.dat pin008.dat

     

    使用序列号时,路径名被用作 java.text.DecimalFormat 的格式字符串。当前序列号作为唯一参数传入。如果未指定开始序列号,则按原样使用路径名称。

    4、格式化序列

    常用的两个格式化序列:

    • #:插入数字,没有前导零或空格。
    • 000:插入数字,数字不足三位时,将插入前导零补足三位;数字超过三位时,则插入数字实际位数。

    用法说明:

    在不带前导零的情况下插入数字:
    pin#'.'dat -> pin1.dat, ... pin9.dat, pin10.dat, ... pin9999.dat
    
    带前导零的情况下插入数字:
    pin000'.'dat -> pin001.dat ... pin099.dat ... pin999.dat ... pin9999.dat
    
    在不带前导零的情况下追加数字:
    pin'.'dat# -> pin.dat1, ... pin.dat9 ... pin.dat999
    

    注意:上面的 . 是格式化字符,必须用单引号括起来。

    2.4.2__FileToString

    把文件读取成一个字符串,每次调用都是读取整个文件。读取文件保存至变量中。

    如果出现打开或读取文件的错误,则函数将返回字符串 **ERR**

    1、我们先来看看这个__FileToString长得是啥样子,路径:函数助手 > 选择__FileToString,如下图所示:

    2、关键参数说明:

    参数描述是否必填
    文件名 文件名的路径。(路径可以相对于JMeter启动目录)
    文件编码 用于读取文件的编码。如果未指定,则使用平台默认值。
    变量名 用于后续调用该函数的变量名称。

    3、实例

    ${__FileToString(C:UsersDELLDesktopuser_info.csv,utf-8,user_info)}

    读取结果可能会出现中文乱码,注意把文件修改成UTF-8的编码格式保存。

    2.4.3__CSVRead

    从文件读取指定列的值(读取固定值/读取动态值/使用文件别名)

    1、我们先来看看这个__CSVRead长得是啥样子,路径:函数助手 > 选择__CSVRead,如下图所示:

    作用

    • 从一个 CSV 文件中返回一个字符串,支持多个文件名。
    • 当第一次调用该函数时,文件将被打开并读取到一个内部数组中。如果检测到空行,这将被视为文件的末尾。
    • 所有对同一文件名的后续引用都使用相同的内部数组,文件名区分大小写。
    • 每个线程都有自己的指向文件数组中当前行的内部指针。当线程首先引用文件时,它将在数组中分配下一个空闲行,因此每个线程将访问与所有其他线程不同的行(除非数组中的线程多于行)。

    2、参数

    参数描述是否必填
    文件名 要读取的文件名
    列号 文件中的列号。0–第一列,1–第二列,next–文件的下一行。

    3、示例

    读取文件中的第1行第1列:
    ${__CSVRead(random.txt,0)}
    
    读取文件中的第1行第2列,并进入文件下一行:
    ${__CSVRead(random.txt,1)}${__CSVRead(random.txt,next)}
    
    读取文件第2行第1列:
    ${__CSVRead(random.txt,0)}
    
    读取文件中的第2行第2列,并进入文件下一行:
    ${__CSVRead(random.txt,1)}${__CSVRead(random.txt,next)}

    读取文件可能会出现中文乱码,修改文件的编码为:ANSI编码格式就可以了。

    注意:

    • 该函数不适合用于大型文件,因为整个文件都存储在内存中。
    • 对于较大的文件,最好使用 CSV Data Set Config 或者 StringFromFile
    • 默认情况下,该函数在每个逗号处拆分行。如果要输入包含逗号的列,则需要通过设置属性将分隔符更改为不出现在任何列数据中的字符,修改 jmeter.properties 文件中的 csvread.delimiter=
    2.4.4__XPath

    根据xpath获取xml节点内容,没有匹配到,则返回空字符串。

    1、我们先来看看这个__Xpath长得是啥样子,路径:函数助手 > 选择__Xpath,如下图所示:

    2、关键参数说明:

    XML file to get values from:待解析的xml文件;

    XPath expression to match against :xpath表达式匹配xml节点 

    注意:

    • 该函数读取 XML 文件,并在文件中寻找与指定 XPath 相匹配的地方。
    • 每调用函数一次,就会返回下一个匹配项。到达文件末尾后,会从头开始。如果没有匹配的节点,那么函数会返回空字符串,另外,还会向JMeter日志文件写一条警告信息。
    • 整个节点列表都会被保存在内存之中,所以文件较大时不适合使用。

    3、示例:

    宏哥找了一个JMeter安装目录下的一个build.xml文件,进行实战,如下:默认取值1,name=all,修改[2],name=run。
    ${__XPath(D:softwareapache-jmeter-5.1.1extrasuild.xml,//target[2]/@name)}

    这会找到 build.xml 文件中的所有目标节点,并返回下一个 name 属性的内容。

     3.小结

    3.1可直接访问变量

    log:直接调用logger函数
    ctx:获取JMeterContent对象
    
    vars:获取JMeter定义的变量
    
    props:获取JMeter配置属性
    
    threadName:获取Jmeter线程名
    
    sampler:获取Sampler实例
    
    sampleResult:获取SamplerResult实例
    
    OUT:类似System.out.println, OUT.println()

       好了,今天到这里JMeter5的函数上篇就介绍和分享完了

  • 相关阅读:
    [你必须知道的.NET] 第四回:后来居上:class和struct
    [你必须知道的.NET]第十回:品味类型值类型与引用类型(下)-应用征途
    [你必须知道的.NET]第十一回:参数之惑传递的艺术(上)
    [你必须知道的.NET] 第一回:恩怨情仇:is和as
    [Anytao.History] 排名进入1000,未来值得努力
    [你必须知道的.NET] 第三回:历史纠葛:特性和属性
    [你必须知道的.NET] 第八回:品味类型值类型与引用类型(上)-内存有理
    [你必须知道的.NET] 第五回:深入浅出关键字把new说透
    [你必须知道的.NET]第十二回:参数之惑传递的艺术(下)
    .NET 3.5
  • 原文地址:https://www.cnblogs.com/lirongyang/p/14116026.html
Copyright © 2011-2022 走看看