1、什麼是邏輯控制器
JMeter官網對邏輯控制器的解釋是:“Logic Controllers determine the order in which Samplers are processed.”
。
意思是說,邏輯控制器可以控制取樣器(Samplers
)的執行順序。
由此可知,控制器需要和取樣器一起使用,否則控制器就沒有什麼意義了。放在控制器下面的所有采樣器,都會當做一個整體,執行時也會一起被執行。
JMeter提供了多種邏輯控制器,它們各個功能都不相同,大概可以分為兩種使用型別:
- 控制測試計劃執行過程中,節點的邏輯執行順序,如:
ForEach Controller
(ForEach控制器),Loop Controller
(迴圈控制器)、If Controller
(如果if控制器)等; - 對測試計劃中的指令碼進行分組,方便JMeter統計執行結果,以及進行指令碼的執行時控制等,如:
Throughput Controller
(吞吐量控制器)、Transaction Controller
(事務控制器)等。
2、如果控制器介紹
在實際工作中,當使用JMeter做效能測試指令碼或者介面測試指令碼時,當遇到需要對不同的條件做不同的操作時,我們可以使用JMeter中如果(If)控制器來實現。
新增如果(If)控制器元件操作:選中“執行緒組”右鍵 —> 新增 —> 邏輯控制器 —> 如果(If)控制器
。
介面如下圖所示:
如果(If)控制器元件介面說明:
- 名稱:如果(If)控制器元件的自定義名稱,見名知意最好。
- 註釋:即新增一些備註資訊,對該如果(If)控制器元件的簡短說明,以便後期回顧時檢視。
Expression (must evaluate to true or false)
:填寫條件表示式,評估結果必須為真或假。
換句話說,是執行流程驗證的條件,用於決定是否應執行子元件。預設情況下,條件被解釋為true
或false
的JavaScript
程式碼。Interpret Condition as Variable Expression?
:將條件解釋為變數表示式?
意思是說:
如果不勾選此選項,則輸入的條件表示式,將會使用JavaScript
進行解析,得到需要的true/false
結果。
如果勾選此選項:
1)輸入的條件表示式,不會使用JavaScript
進行解析,而是將條件視為JMeter的變數。
2)如果需要進行條件判斷,則需要使用__jexl3
或者__groovy
函式,來生成函式表示式。通過函式表示式,得到需要的true/false
結果。Evaluate for all children?
:條件作用於每個子項進行評估。
如果勾選該項,則該控制器在每一個子節點執行時前,執行一次。
預設情況下,該控制器可以對在其下面的所有可執行的元件,進行控制執行,但只在入口執行一次。
說明:
For performance it is advised to check "Interpret Condition as Variable Expression" and use `__jexl3` or `__groovy` evaluating to true or false or a variable that contains true or false. ${JMeterThread.last_sample_ok} can be used to test if last sampler was successful
意思為:
- 為了提升效能,建議將“將條件解釋為變數表示式”勾選。
- 並使用
__jexl3
或者__groovy
函式,來評估表示式條件的真假。- 並且
${JMeterThread.last_sample_ok}
變數,可用於測試最後一個取樣器是否成功。預設“將條件解釋為變數表示式”是勾選狀態,取消勾選,則上面的提示會變紅。
3、如果控制器的使用
(1)測試計劃內包含的元件
新增元件操作步驟:
- 建立測試計劃。
- 建立執行緒組:
選中“測試計劃”右鍵 —> 新增 —> 執行緒(使用者) —> 執行緒組
。 - 線上程組中,新增邏輯控制器“如果(If)控制器”元件:
選中“執行緒組”右鍵 —> 新增 —> 邏輯控制器 —> 如果(If)控制器
。 - 在邏輯控制器中,新增取樣器“HTTP請求”元件:
選中“邏輯控制器”右鍵 —> 新增 —> 取樣器 —> HTTP請求
。 - 線上程組中,新增監聽器“察看結果樹”元件:
選中“執行緒組”右鍵 —> 新增 —> 監聽器 —> 察看結果樹
。
最終測試計劃中的元件如下:
點選執行按鈕,會提示你先儲存該指令碼,指令碼儲存完成後會直接自動執行該指令碼。
(2)如果控制器介面內容
我們演示使用JavaScript
解析表示式的用法,步驟如下:
- 取消勾選
Interpret Condition as Variable Expression?
選項,否則將不能使用JavaScript
解析表示式。 - 在條件輸入框中,輸入最基本的條件表示式即可。
我編寫了一個恆true的表示式,如下圖所示:
(3)HTTP請求介面內容
一個標準的 Get請求,訪問百度首頁,不做過多說明。
如下圖所示:
(4)執行結果
因為如果(If)控制器中的表示式為true
,所以可以執行它下面的所有取樣器請求。
如下圖所示:
若如果(If)控制器中的表示式解析結果為false
,則該控制器下面的請求則不執行。
4、如果控制器中表示式的寫法
如果(If)控制器中的表示式有兩種方式:
- 一種使用
JavaScript
語言解析條件表示式,表示式為基本的條件表示式寫法。 - 另一種是使用
__jexl3
或者__groovy
函式,通過函式表示式,得出我們需要的true
或false
結果。
(1)使用JavaScript
語言解析表示式
即:取消勾選Interpret Condition as Variable Expression?
選項。
最基本的幾種寫法:
- 數字判斷表示式:
${var}==1
。 - 字串判讀表示式:
"${var}"=="字串"
。
提示:如果${var}
引數化變數取到的值本身就帶雙引號,則前邊不需要加雙引號。 - 如果
${var}
引數化變數的值就是一個布林值,則表示式為:${var}
。
但是要注意,布林值變數必須都是小寫的。
說明:
${var}
表示引數化變數的引用。我們可以引用自定義變數,或者CSV檔案讀取到的資料,在或者是上一個請求中提取來的值。
(2)使用函式來編寫條件表示式
即:勾選Interpret Condition as Variable Expression?
選項。
我們需要用到函式助手中的__jexl3
或者__groovy
函式,直接輸出true/false
結果。
下面以__jexl3
函式為示例,進行演示。
__jexl3
函式介面如下:
引數說明:
JEXL expression to evaluate
:填寫要計算的表示式。Name of variable in which to store the result (optional)
:給函式結果定義一個可被引用的變數名(可選)。
__jexl3
函式條件格式:${__jexl3(條件表示式)}
==
是否等於,如${__jexl3(${VAR}==1,)}
,判斷${VAR}
變數是否等於1。!=
不等於,如${__jexl3(${VAR}!=1,)}
,判斷${VAR}
變數是否不等於1。!
非,如${__jexl3(!(${VAR}!=1),)}
,對${VAR}!=1
的結果取反。&&
且和||
或,如${__jexl3(${VAR}==1 && "${name}" != "張三",)}
。>
大於或者>=
大於等於,如${__jexl3(${count}>=10,)}
。
編輯好的介面內容如下:
提示:
- 把生成的
__jexl3
函式表示式,貼上到如果(If)控制器介面中。- 看到
The result of the function is
中有值,說明表示式正確,但是上面返回false這個值,不一定正確,還要看指令碼執行中實際的結果。
這樣就完成了使用__jexl3
函式編寫表示式的用法。(__groovy
函式同理)
說明:
儘可能使用"解釋條件作為變數表示式"選項,然後使用
__jexl3
或者__groovy
函式生成條件表示式。因為執行模擬大量使用者的效能指令碼時,這樣消耗的資源最小。
WHY?
If Controller
使用JavaScript
解釋條件,是每個解釋都佔用資源,但本來就是一個測試效能的軟體,不應因解析條件而消耗更多的資源。即:如果你使用“解釋條件作為變數表示式”,而不是使用
Javascript
解釋表示式,這樣能節省更多的效能資源。
(3)Evaluate for all children?
選項說明
如果你勾選了Interpret Condition as Variable Expression?
選項,同時也勾選了Evaluate for all children?
選項。
則填寫在如果(If)控制器中的表示式,需要為${JMeterThread.last_sample_ok}
。
${JMeterThread.last_sample_ok}
表示式的意思是:檢查上一個請求是否成功。
而整個控制流程的效果是,控制其下的所有取樣器:
- 如果前一個請求為成功,則
${JMeterThread.last_sample_ok}
為true,否則為false。 - 下一個請求拿
${JMeterThread.last_sample_ok}
的值來判斷是否執行,如果為true,則繼續執行,如果為false則不執行,且後邊的所有請求都不執行。
如下圖所示:
5、擴充
有一個小示例:我準備了20多條測試資料,但是我只想執行指定的幾個測試資料。
有什麼解決辦法嗎?
測試資料如下所示:
(1)需求:執行指定的用例5
這時我們可以id
為作為條件判斷,來執行用例5。
表示式為:${__jexl3(${id} == 5,)}
(2)需求:執行奇偶數用例
- 執行奇數用例,表示式為:
${__jexl3(${id}%2 == 1,)}
- 執行偶數用例,表示式為:
${__jexl3(${id}%2 == 0,)}
(3)執行多條隨機指定用例
- 5條以內用
||
來解決。 - 5條以上,使用在構造資料中打標籤的方式來實現。
run
欄位,1表示執行,0表示不執行。
表示式為:${__jexl3(${run} == 1,)}
(4)提示
以後工作中的控制器千萬不要寫成下面這樣哦!