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)提示
以后工作中的控制器千萬不要寫成下面這樣哦!