jmeter函式和變數(一)
概述
對jmeter函式進行一次全面複習,依據是官網的文件版本3.2。本來想一篇寫完的,中間做專案和一些雜事拖了2個禮拜,再回來寫的時候發現太長了~還是分開寫比較妥當。先放出一部分吧。
函式和變數
JMeter函式是一種特殊的值,可以在測試樹中填充任何取樣器或其他元素的欄位。函式呼叫如下:
${__functionName(var1,var2,var3)}
“__functionName”與具體的函式名匹配。圓括號內是傳遞給函式的引數,例如${__time(YMD)},實際的引數因函式而異。不需要引數的函式可以去掉括號,例如${__threadNum}。
如果一個函式引數包含一個逗號,那麼一定要用”\”來轉義,否則JMeter將把它作為一個引數分隔符。
例如:
${__time(EEE\, d MMM yyyy)}
如果逗號沒有轉義,將會有異常丟擲
${__javaScript(Math.max(2,5))}
ERROR - jmeter.functions.JavaScript: Error processing Javascript: [Math.max(2]
org.mozilla.javascript.EvaluatorException: missing ) after argument list (<cmd>#1)
這是因為字串”Math.max(2,5)”被看作是__javascript函式的兩個引數:”Math.max(2” 和 “5)”
變數被引用如下:
${VARIABLE}
如果引用一個未定義的函式或變數,JMeter不會報告/記錄一個錯誤——引用沒有改變。例如,如果沒有定義變數UNDEF,那麼${UNDEF}的值就是${UNDEF}。變數,函式(或者屬性)都是區分大小寫的。在使用jmeter變數之前,JMeter會刪除變數前後的空格,例如${__Random(1,63, LOTTERY )}將會使用變數’LOTTERY’而不是’ LOTTERY ‘(這個前後各有一個空格)。
屬性與變數不同。變數是執行緒的區域性變數;屬性在所有執行緒中都是通用的,並且需要使用__P或__property函式來引用。
當在一個windows路徑的變數之前使用”\”,例如C:\test\
摘自官網:
Type of function | Name | Comment | Since |
---|---|---|---|
Information | threadNum | get thread number | 1.X |
Information | samplerName | get the sampler name (label) | 2.5 |
Information | machineIP | get the local machine IP address | 2.6 |
Information | machineName | get the local machine name | 1.X |
Information | time | return current time in various formats | 2.2 |
Information | log | log (or display) a message (and return the value) | 2.2 |
Information | logn | log (or display) a message (empty return value) | 2.2 |
Input | StringFromFile | read a line from a file | 1.9 |
Input | FileToString | read an entire file | 2.4 |
Input | CSVRead | read from CSV delimited file | 1.9 |
Input | XPath | Use an XPath expression to read from a file | 2.0.3 |
Calculation | counter | generate an incrementing number | 1.X |
Calculation | intSum | add int numbers | 1.8.1 |
Calculation | longSum | add long numbers | 2.3.2 |
Calculation | Random | generate a random number | 1.9 |
Calculation | RandomFromMultipleVars | extracts an element from the values of a set of variables separated by | |
Calculation | RandomString | generate a random string | 2.6 |
Calculation | UUID | generate a random type 4 UUID | 2.9 |
Scripting | groovy | run a Groovy script | 3.1 |
Scripting | BeanShell | run a BeanShell script | 1.X |
Scripting | javaScript | process JavaScript (Nashorn) | 1.9 |
Scripting | jexl2 | evaluate a Commons Jexl2 expression | jexl2(2.1.1) |
Scripting | jexl3 | evaluate a Commons Jexl3 expression | jexl3 (3.0) |
Properties | property | read a property | 2 |
Properties | P | read a property (shorthand method) | 2 |
Properties | setProperty | set a JMeter property | 2.1 |
Variables | split | Split a string into variables | 2.0.2 |
Variables | V | evaluate a variable name | 2.3RC3 |
Variables | eval | evaluate a variable expression | 2.3.1 |
Variables | evalVar | evaluate an expression stored in a variable | 2.3.1 |
String | regexFunction | parse previous response using a regular expression | 1.X |
String | escapeOroRegexpChars | quote meta chars used by ORO regular expression | 2.9 |
String | char | generate Unicode char values from a list of numbers | 2.3.3 |
String | unescape | Process strings containing Java escapes (e.g. \n & \t) | 2.3.3 |
String | unescapeHtml | Decode HTML-encoded strings | 2.3.3 |
String | escapeHtml | Encode strings using HTML encoding | 2.3.3 |
String | escapeXml | Encode strings using XMl encoding | 3.2 |
String | urldecode | Decode a application/x-www-form-urlencoded string | 2.1 |
String | urlencode | Encode a string to a application/x-www-form-urlencoded string | 2.1 |
String | TestPlanName | Return name of current test plan | 2.6 |
函式能做什麼
有兩種函式:使用者定義的靜態值(或變數)和內建函式。
使用者定義的靜態值允許使用者定義變數,當測試樹被編譯並提交執行時,這些變數將被替換為靜態值。
替換在測試執行第一次開始時發生。用於替換所有HTTP請求的域欄位,例如,將同一個測試用例測試不同伺服器的將變成一個簡單的問題。
注意:變數不能被巢狀,例如${Var${N}}將不起作用. __V (variable)函式可以用來做變數替換: ${__V(Var${N})}. 你也可以使用 ${__BeanShell(vars.get(“Var${N}”)}.
這種型別的替換在沒有函式的情況下是可能的,但是不那麼方便,也不那麼直觀。它要求使用者建立預設的配置元素,這些元素將填充Samplers的空白值。變數允許只替換任何給定值的一部分,而不只是填充空白值。
有了內建函式,使用者可以在執行時根據之前的響應資料計算新值,以及該函式所在的執行緒、耗時和許多其他資訊。在整個測試過程中,這些值會在每個請求後重新整理。
函式是執行緒共享的,在測試中每次函式呼叫由函式的不同例項處理
函式和變數在哪裡使用
函式和變數可以寫入任何測試元件的任何欄位(除了測試計劃之外)。有些欄位不允許隨機字串,因為它們期望數字,因此不會接受一個函式。但是,大多數字段都允許函式。
在測試計劃中使用的函式有一些限制。在處理函式時,JMeter執行緒變數將不會被完全設定,因此變數名作為一個引數傳入,不會被設定,變數引用也不會起作用,因此split()和regex()和變數評估函式將不會起作用。threadNum()函式不會起作用(在測試計劃級別上沒有意義)。以下功能應該在測試計劃中起作用:
- intSum
- longSum
- machineName
- BeanShell
- groovy
- javaScript
- jexl2/jexl3
- random
- time
- property functions
- log functions
配置元素由一個單獨的執行緒處理。因此,諸如__threadNum這樣的函式在諸如使用者定義的變數之類的元素中不能正常工作。還要注意,在UDV元素中定義的變數在處理元素之前是不可用的。
在SQL中使用變數/函式引用是,記得字串包含必要的引號
SELECT item from table where name=’${VAR}’
而不是
SELECT item from table where name=${VAR}
(除非字串本身包含引號)
如何引用變數和函式
在測試元素中引用變數是通過 ‘${}’將變數包含起來 如${var}。
函式以相同的方式引用,但按照約定,函式名以”__”開頭,避免與使用者值名稱衝突,一些函式使具有引數,這些函式引數以逗號分隔。如果函式不帶引數,則可以省略括號。若引數值本身包含逗號,應該在必要時轉義: “\,”,這適用於指令碼函式——Javascript、Beanshell、Jexl、groovy在指令碼方法呼叫中,需要避免任何可能需要的逗號。
${__BeanShell(vars.put("name"\,"value"))}
另外一種方法可以將指令碼定義成一個變數:
SCRIPT vars.put("name","value")
指令碼可以引用如下:
${__BeanShell(${SCRIPT})}
這裡不需要轉義SCRIPT變數中的逗號,因為函式呼叫在變數替換為它的值之前被解析。這與JSR223或BeanShell的取樣器能夠很好的配合,因為這些可以用來測試Javascript、Jexl和BeanShell指令碼。
函式可以引用變數和其他函式,例如${__XPath(${__P(xpath.file),${XPATH})} 將使用屬性”xpath.file”作為檔名,變數XPATH要搜尋的表示式的內容。
JMeter提供了一個工具來幫助建構函式呼叫,用於各種內建函式,然後就可以複製貼上了。
它不會自動轉義,因為函式可以是其他函式的引數,應該只轉義想要的值。
If a string contains a backslash(‘\’) and also contains a function or variable reference, the backslash will be removed if it appears before ‘$’ or ‘,’ or ‘\’. This behaviour is necessary to allow for nested functions that include commas or the string ${. Backslashes before ‘$’ or ‘,’ or ‘\’ are not removed if the string does not contain a function or variable reference.
變數或函式的值可以使用__logn()函式進行報告。在定義變數之後,__logn()函式引用可以在測試計劃的任何地方使用。或者,可以使用Java請求取樣器可以建立包含變數引用的樣例;輸出將顯示在適當的偵聽器中。
注意,在樹檢視監聽器中有一個可以用來顯示變數值的除錯取樣器(Debug Sampler)。
如果定義一個使用者定義的靜態變數,其名稱與內建函式相同,那麼您的靜態變數將會覆蓋內建函式。
函式幫助對話方塊
函式幫助對話方塊可以從Jmeter的選單中調出
使用函式幫助器,您可以從下拉中選擇一個函式,併為其引數指定值。表中的左列提供了對該引數的簡要描述,而右邊的列是您在該引數的值中寫入的位置。不同的函式有不同的引數。
一旦您完成了這個操作,點選“generate”按鈕,就會生成適當的字串,以便您可以在您喜歡的地方複製貼上到您的測試計劃中。
函式
__regexFunction
函式用於使用任何正則表示式(由使用者提供)解析以前的響應(或變數的值)。函式返回帶有變數值的模板字串。
__regexFunction還可以儲存起來,以便供後續使用。在第六個引數中,可以指定一個引用名稱。在執行該函式之後,可以在稍後使用使用者定義值的語法檢索相同的值。
例如,如果您輸入”refName”作為第六個引數,您將能夠使用:
- ${refName}來引用第2個引數(替換字串模板)的計算結果,這依賴於函式的解析結果。
- ${refName_g0}來引用函式解析後發現的所有匹配結果。
- ${refName_g1}來引用函式解析後發現的第一個匹配組合。
- ${refName_g#}來引用函式解析後發現的第n個匹配組合。
- ${refName_matchNr}來引用函式總共發現的匹配組合數目
Attribute | Description | Required |
---|---|---|
第1個引數 | 第1個引數是用於解析伺服器響應資料的正則表示式。它會找到所有匹配項。如果希望將表示式中的某部分應用在模板字串中,一定記得為其加上圓括號。例如,<a href=”(.*)”>。這樣就會將連結的值存放到第一個匹配組合中(這裡只有一個匹配組合)。又如,。在這個例子中,連結的name作為第一個匹配組合,連結的value會作為第二個匹配組合。這些組合可以用在的模板字串中 | 是 |
第2個引數 | 這是一個模板字串,函式會動態填寫字串的部分內容。要在字串中引用正則表示式捕獲的匹配組合,請使用語法:$[group_number]$。例如$1$或者 $2$。的模板可以是任何字串 | 是 |
第3個引數 | 第3個引數告訴JMeter使用第幾次匹配。正則表示式可能會找到多個匹配項。對此,有4種選擇:1)整數,直接告訴JMeter使用第幾個匹配項。”1”對應第一個匹配,”2”對應第二個匹配,以此類推2)RAND,告訴JMeter隨機選擇一個匹配項3)ALL,告訴JMeter使用所有匹配項,為每一個匹配項建立一個模板字串,並將它們連線在一起4)浮點值0到1之間,根據公式(找到的總匹配數目*指定浮點值)計算使用第幾個匹配項,計算值向最近的整數取整 | 否,預設值為1 |
第4個引數 | 如果在上一個引數中選擇了”ALL”,那麼這第4個引數會被插入到重複的模板值之間,就是說有多個地方匹配模版,這多個匹配之間用該引數的值進行分割 | 否 |
第5個引數 | 如果沒有找到匹配項返回的預設值 | 否 |
第6個引數 | 重用函式解析值的引用名。儲存${refName}和${refName_g#} “#”是正則表示式匹配到組的數量(“0”可以使用,是全部匹配) | 否 |
第7個引數 | 輸入變數名稱。如果指定了這一引數,那麼該變數的值就會作為函式的輸入,而不再使用前面的取樣結果作為搜尋物件 | 否 |
舉個栗子!還是以百度的首頁搜尋為例。一共有兩個斷言,見截圖。
第一個斷言正則表示式$1$ $2$返回結果為kw wd;第二個斷言直接引用refName_g0(在第一個斷言中使用的第六個引數),結果為<input id=kw name=wd class=s_ipt value maxlength=255
因為在上面的例子中正則表示式中並沒有出現多個匹配的模版所以設定的第四個引數tmp沒有起作用,下面做個演示只是用http關鍵字進行匹配,並制定第四個引數為SSS
是不是第四個引數已經生效了
現在演示一下正則表示式中應用自定義變數
__counter
這個函式是一個計數器,用於統計函式的使用次數,從1開始每次加1。計數器既可以被配置成針對每個虛擬使用者是獨立的,也可以被配置成所有虛擬使用者公用的。如果每個虛擬使用者的計數器是獨立增長的,那麼通常被用於記錄測試計劃運行了多少遍。全域性計數器通常被用於記錄傳送了多少次請求。計數器使用一個整數值來記錄,允許的最大值為2,147,483,647。
計數器函式例項是完全獨立的。全域性計數器 “FALSE”是由每個計數器例項單獨維護的。
在同一個迭代中,多個計數器函式(__counter)呼叫不會進一步增加值。如果想要為每個示例增加一個增量,請在預處理程式中使用該函式,例如使用者引數。
Attribute | Description | Required |
---|---|---|
第1個引數 | True,如果希望每個虛擬使用者的計數器保持獨立,與其他使用者的計數器相區別。false,全域性計數器 | 是 |
第2個引數 | 重用計數器函式建立值的引用名。可以這樣引用計數器的值:${refName}。這樣就可以建立一個計數器後,在多個地方引 | 否 |
格式:${__counter(FALSE,test)}
我們將”__counter”函式生成的引數複製到某個引數下面(一般使用的時候會放在對應的取樣器中,見__threadNum例子),如果為TRUE格式,則每個執行緒各自統計,最大數為迴圈數,如果為FALSE,則所有執行緒一起統計,最大數為執行緒數乘以迴圈數
下面是設定了10個執行緒迴圈5次執行的結果:自定義的mycountervar在持續增加~~
當然也可以使用執行緒組的配置元件–計數器來實現計數
__threadNum
函式__threadNum只是簡單地返回當前執行緒的編號。執行緒編號不依賴於執行緒組,這就意味著從函式的角度看來,某個執行緒組的執行緒#1和另一個執行緒組的執行緒#1是沒有區別的。另外,該函式沒有引數。
格式:${__threadNum}
返回一個1到執行緒組中配置的執行執行緒的最大數之間的一個數字
這一函式不能用在任何配置元件中(如使用者定義的變數),原因在於配置元件是由一個獨立執行緒執行的。另外在測試計劃(Test Plan)中使用也是沒有意義的。
__intSum
__intSum函式分別用來進行整型。這兩個函式均為可變引數列表的函式,可用來進行任意個整型資料的加法運算。
用於計算多個整數的和,可以是計算正整數和負整數的和,它有N個引數,最少有3個引數,最多不限。最後一個引數是函式名稱,前面的其它參 數是要求和的整數。這個函式在函式對話方塊中只顯示3個引數,如果要計算多個整數,可以通過新增引數實現,不過最後一個引數一定要是函式名稱。再新增的引數 會在函式名稱後面,這個時候,需要我們手動將函式名稱引數放到最後一個。
Attribute | Description | Required |
---|---|---|
第1個引數 | 第1個整數值 | 是 |
第2個引數 | 第2個整數值 | 是 |
… | … | … |
第n個引數 | 第n個整數值 | 否 |
最後一個引數 | 函式計算值的引用名。如果使用者指定了這一引數,那麼引用名中必須包含一個非數字字母,否則它會被當成另一個整數值,而被函式用於計算 | 否 |
在HTTP請求中設定函式,經過除錯檢視儲存計算的結果
__longSum
__longSum與__intSum函式分別用來進行長整型和整型資料的加法運算,幾乎一樣
不再做介紹
見__intSum
__StringFromFile
函式__StringFromFile可以被用來從文字檔案中讀取字串。這對於需要大量可變資料的測試很有用。例如,當測試一個銀行應用系統時,可能需要100條甚至1000條賬戶資訊。
使用配置元件CSV Data Set Config ,也能達到相同的目的,而且方法更簡單。但是該配置元件目前不支援多輸入檔案。
每次呼叫函式,都會從檔案中讀取下一行。當到達檔案末尾時,函式又會從檔案開始處重新讀取,直到最大迴圈次數。如果在一個測試指令碼中對該函式有多次引用,那麼每一次引用都會獨立開啟檔案,即使檔名是相同的(如果函式讀取的值,在指令碼其他地方也有使用,那麼就需要為每一次函式呼叫指定不同的變數名)。
函式例項是線上程之間共享的,當執行緒需要輸入時開啟或重新開啟檔案,因此使用threadNumber作為檔名的一部分將導致不可預測的行為。
如果在開啟或者讀取檔案時發生錯誤,那麼函式就會返回字串”**ERR**”。
Attribute | Description | Required |
---|---|---|
檔名 | 檔名(可以使用相對於JMeter啟動目錄的相對路徑)。如果要在檔名中使用可選的序列號,那麼檔名必須適合轉成十進位制格式。 | 是 |
變數名 | 一個引用名(refName),目的是複用這一函式建立的值。可以使用語法${refName}來引用函式建立的值。預設值為”StringFromFile_” | 否 |
初始序列 | 號初始序列號(如果省略這一引數,終止序列號會作為一個迴圈計數器) | 否 |
終止序列 | 號終止序列號(如果省略這一引數,序列號會一直增加下去,不會受到限 制) | 否 |
當開啟或者重新開啟檔案時,檔名引數將會被解析。
每次執行函式時,引用名引數(如果支援)將會被解析。
使用序列號:
當使用可選的序列號時,檔名需要使用格式字串Java.text.DecimalFormat。當前的序列號會作為唯一的引數。如果不指明可選的初始序列號,就使用檔名作為起始值。一些有用的格式序列如下:
#:插入數字,數字前面不能有0,也不包含空格。
000:插入數字,包含3個數字組合,位數不足使用0在左側補齊指定的位數,超過位數的按實際位置輸出。
例如:
寫法 | 解釋 |
---|---|
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 |
如果不希望某個格式字元被翻譯,需要為它加上單引號。注意”.”是格式字元,必須被單引號所包含。
如果路徑名不包含任何特殊的格式化字元,那麼當前的序列號將被追加到名稱中,否則將根據格式化指令插入數字。
如果省略了初始序列號,且指定了終止序列號,則終止序列號理解為迴圈的次數,檔案將被重複執行指定次數,在這種情況下檔名將不被格式化轉義,直接匹配。例如:
${_StringFromFile(PIN#'.'DAT,,1,2)}:讀取 PIN1.DAT, PIN2.DAT。
${_StringFromFile(PIN.DAT,,,2)}:讀取 PIN.DAT 兩次。
注意: “.”在PIN.DAT並沒有使用引號引著,在這個用例中起始序列號省略,所以檔名精確匹配
__machineName
函式__machineName返回本機的主機名。使用java方法InetAddress.getLocalHost()傳給getHostName()。只有一個引數:引用名,非必須
Attribute | Description | Required |
---|---|---|
引用名 | 該函式返回值儲存起來,以便複用 | 否 |
__machineIP
函式__machineIP返回本機的主機IP。使用java方法InetAddress.getLocalHost()傳給getHostName()。只有一個引數:引用名,非必須
Attribute | Description | Required |
---|---|---|
引用名 | 該函式返回值儲存起來,以便複用 | 否 |