Jmeter(二十三) – 從入門到精通 – JMeter函數 – 上篇(詳解教程)

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%\bin\jmeter.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:\Users\DELL\Desktop\user_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:\software\apache-jmeter-5.1.1\extras\build.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的函數上篇就介紹和分享完了,感謝您耐心的閱讀和一路支持宏哥!!!

Tags: