如何在 JMeter 中將變數從一個線程組傳遞到另一個線程組
1. 簡介
在本快速教程中,我們將探討如何在 JMeter 執行緒組之間共用變數。當一個執行緒組執行設定任務(例如身份驗證或資料準備),而另一個執行緒組使用結果時,這是一種常見的需求。
由於 JMeter 變數對於每個執行緒來說都是本地的,我們將探索一些以簡單且更強大的方式在群組之間傳遞資料的技術。
2. 場景和設定
我們的測試場景涉及兩個操作:
- 將一些資料發佈到端點,傳回一個 UUID
- 在後續的 GET 請求中使用該 UUID 來檢索已發布的數據
我們將把這些操作分成兩個執行緒組:
- 第一個執行緒群組處理 POST 請求並儲存傳回的 UUID
- 第二個線程組使用儲存的 UUID 執行 GET 請求
2.1. 建立設定線程組
由於 JMeter 預設同時執行執行緒組,因此我們將使用特殊的執行緒組類型來控制執行順序。
讓我們右鍵單擊測試計劃,然後選擇:
Add -> Threads (Users) -> setUp Thread Group
這可確保設定邏輯(即 POST 請求和保存變數)在其他執行緒組開始之前執行。
2.2. 發布隨機數據
要發布隨機測試數據,我們將使用帶有${__RandomString(5)}
簡單 HTTP 請求元素:
在每種方法中,我們都會在 POST 請求後使用JSR223 後處理器元素,以便跨線程群組共享地檢索和保存回應文字。然後,我們會在 GET 請求前使用JSR223 預處理器,檢索已儲存的回應值,並在請求中使用它。最重要的是,我們將使用 Java 作為腳本語言。
2.3. 了解 JMeter 上下文變數
使用 JMeter 元件(例如取樣器、預處理器或後處理器)時,我們可以存取內建腳本變數。在本教程中,我們將使用prev
、 props
和vars
:
-
prev
:上一個採樣器的SampleResult
,通常為 HTTP 請求,用於提取回應主體和狀態碼 -
props
:JMeterProperties
對象,它是整個測試的全域對象,可用於在執行緒或執行緒組之間共用值 -
vars
:目前執行緒的 JMeter 變量,可用於在元件中讀取或寫入值(可透過${}
語法存取)
3.使用JMeter屬性
跨線程組共享值的最簡單方法是透過props
。這些值在整個測試執行過程中共享,並在整個執行過程中持續存在:
String response = prev.getResponseDataAsString();
props.put("uuid", response);
注意, props
變數是一個Object
類型的映射,因此我們並不局限於使用String
值。然後,在另一個線程組中,我們可以檢索它並將其儲存在vars
中,以便其他元素可以使用它:
String uuid = props.get("uuid");
vars.put("uuid", uuid);
一旦儲存在vars
中,我們就可以在 HTTP 請求或其他測試元素中使用${uuid}
語法:
屬性在線程和線程組之間共享,這對於單一值或設定線程組僅使用一個線程的情況非常有效。讓我們看看當需要更複雜的協調時的其他方法。
4. 使用bsh.shared
命名空間
一個更靈活(但更老)的選項是使用 BeanShell 共享命名空間bsh.shared
,它就像一個全局對象存儲,在整個測試計劃中所有 BeanShell 腳本之間共享。這種技術在共享更複雜的資料結構(例如佇列或映射)時非常有用。
讓我們建立一個新變數uuidQueue
。我們將透過將其與void
進行比較來檢查它是否已定義,然後將其初始化為LinkedList
:
String response = prev.getResponseDataAsString();
if (bsh.shared.uuidQueue == void) {
bsh.shared.uuidQueue = new LinkedList();
}
然後我們可以正常使用它來新增項目:
bsh.shared.uuidQueue.add(response);
相反,要在另一個線程組中檢索它:
String uuid = bsh.shared.uuidQueue.poll();
vars.put("uuid", uuid);
需要注意的是,BeanShell 被認為比 Groovy 或純 Java 腳本更慢且更不安全。
5. 寫入和讀取文件
當我們需要在運行之間實現完全的可見性或持久性時,基於文件的通訊是另一個可行的選擇,儘管它更冗長。在本例中,我們將使用ctx.getThreadNum()
根據線程號建立單獨的檔案:
String response = prev.getResponseDataAsString();
File file = new File("/tmp/shared-file" + ctx.getThreadNum() + ".txt");
然後,編寫文件的標準樣板是:
try {
FileWriter writer = new FileWriter(file);
writer.write(response);
writer.close();
} catch (IOException e) {
log.error("Failed to write file", e);
}
最後,我們將其讀出來:
File file = new File("/tmp/shared-file" + ctx.getThreadNum() + ".txt");
try {
Scanner reader = new Scanner(file);
String uuid = reader.hasNextLine() ? reader.nextLine().trim() : "";
reader.close();
vars.put("uuid", uuid);
} catch (IOException e) {
log.error("Failed to read file", e);
}
優點:
- 適用於調試、持久化或運行間的手動操作
- 對於較大的資料集或批量導出更安全
缺點:
- 由於磁碟 I/O 而變慢
- 必須仔細管理文件清理和線程特定路徑
6. 結論
在本文中,我們研究了在 JMeter 中線程組之間傳遞資料的幾種技術。 JMeter Properties 適用於簡單的單值資料共用。對於進階場景,例如執行緒佇列或持久化測試工件, bsh.shared
雖然比較老,但仍然很有幫助。最後,我們介紹了一種基於文件的方法,可以提供更大的靈活性。
與往常一樣,原始碼可在 GitHub 上取得。