Các biến tích hợp sẵn trong BeanShell
Trong JMeter, BeanShell cung cấp một tập hợp các biến mặc định cho phép tương tác trực tiếp với ngữ cảnh thực thi. Dưới đây là các biến quan trọng và cách ứng dụng:
log: Ghi thông tin gỡ lỗi vào filejmeter.loghoặc hiển thị trên console.vars: Đối tượngJMeterVariables, dùng để thao tác với các biến cục bộ trong phạm vi Thread Group (get, put).props: Đối tượngJMeterProperties, thao tác với các thuộc tính toàn cục, có thể chia sẻ giữa nhiều Thread Group.ctx: Đại diện choJMeterContext, cung cấp quyền truy cập vào thông tin luồng hiện tại, request và response.prev: Tham chiếu đếnSampleResultcủa request ngay trước đó, dùng để trích xuất dữ liệu phản hồi.
Ngoài ra, bạn có thể truy cập các thuộc tính của SampleResult thông qua prev như:
prev.getResponseDataAsString(): Lấy nội dung body của response dưới dạng chuỗi.prev.getResponseCode(): Lấy mã trạng thái HTTP (ví dụ: 200).prev.getResponseHeaders(): Lấy toàn bộ header của response.prev.setSuccessful(boolean)hoặcFailure: Thiết lập trạng thái thành công hay thất bại của sample.
Sử dụng BeanShell Sampler để tạo dữ liệu động
BeanShell Sampler thường được dùng để sinh dữ liệu phức tạp mà các hàm có sẵn của JMeter không đáp ứng được. Ví dụ, tạo mã định danh ngẫu nhiên và lưu vào biến.
Sự khác biệt cốt lõi giữa vars và props là phạm vi hoạt động: vars chỉ tồn tại trong một Thread Group, trong khi props có giá trị trên toàn bộ Test Plan.
Xử lý Response với BeanShell PostProcessor
Khi cần phân tích cú pháp hoặc biến đổi dữ liệu trả về, BeanShell PostProcessor là lựa chọn tối ưu. Thông qua biến prev (tương đương ctx.getPreviousResult()), ta có thể đọc và xử lý response trước khi chuyển sang bước tiếp theo.
Các kịch bản mẫu và tối ưu hóa mã nguồn
1. Sinh mã định danh ngẫu nhiên không chứa ký tự đặc biệt
import java.util.UUID;
// Tạo UUID và loại bỏ dấu gạch ngang
String rawUuid = UUID.randomUUID().toString();
String formattedId = rawUuid.replace("-", "").toUpperCase();
// Lưu vào biến JMeter để sử dụng ở các request sau
vars.put("generated_transaction_id", formattedId);
log.info("New Transaction ID: " + formattedId);
2. Ghép chuỗi tham số từ danh sách biến động
Giả sử bạn cần gom nhiều ID từ một Regular Expression Extractor thành một chuỗi JSON array.
int matchCount = Integer.parseInt(vars.get("user_ids_matchNr"));
StringBuilder jsonPayload = new StringBuilder("[");
if (matchCount > 0) {
for (int i = 1; i <= matchCount; i++) {
String currentId = vars.get("user_ids_" + i);
jsonPayload.append("{\"userId\":\"").append(currentId).append("\",\"status\":\"active\"}");
if (i < matchCount) {
jsonPayload.append(",");
}
}
}
jsonPayload.append("]");
vars.put("final_user_payload", jsonPayload.toString());
3. Ghi dữ liệu trích xuất ra file CSV
import java.io.BufferedWriter;
import java.io.FileWriter;
int recordCount = Integer.parseInt(vars.get("order_refs_matchNr"));
String filePath = "extracted_orders.csv";
if (recordCount > 0) {
// Sử dụng try-with-resources để tự động đóng stream
try (BufferedWriter writer = new BufferedWriter(new FileWriter(filePath, true))) {
for (int i = 1; i <= recordCount; i++) {
String orderRef = vars.get("order_refs_" + i);
writer.write(orderRef + "\n");
}
} catch (Exception e) {
log.error("Error writing to file: " + e.getMessage());
}
}
4. Tích hợp thư viện JAR tùy chỉnh
Đặt file JAR vào thư mục jmeter/lib và khởi tạo lớp mã hóa.
import com.mycompany.crypto.AESEncryptor;
AESEncryptor encryptor = new AESEncryptor();
String secretKey = "MySecretKey12345";
String rawData = vars.get("sensitive_payload");
String encryptedData = encryptor.encrypt(rawData, secretKey);
vars.put("encrypted_payload", encryptedData);
5. Tùy chỉnh Assertion (BeanShell Assertion)
Đoạn mã dưới đây kiểm tra xem response có chứa mã lỗi cụ thể hay không. Lưu ý: Chỉ sử dụng trong BeanShell Assertion.
String responseBody = prev.getResponseDataAsString();
String expectedToken = "\"errorCode\":\"SUCCESS\"";
if (responseBody != null && responseBody.contains(expectedToken)) {
Failure = false; // Đánh dấu sample thành công
} else {
Failure = true; // Đánh dấu sample thất bại
FailureMessage = "Validation failed. Expected token not found in response.";
log.error(FailureMessage + " | Actual response: " + responseBody);
}
6. Định dạng thời gian tùy chỉnh
import java.text.SimpleDateFormat;
import java.util.Calendar;
Calendar cal = Calendar.getInstance();
cal.add(Calendar.DAY_OF_MONTH, 1); // Lấy ngày mai
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
String futureDate = formatter.format(cal.getTime());
vars.put("tomorrow_timestamp", futureDate);
7. Chia sẻ dữ liệu giữa các Thread Group
Để truyền token từ luồng đăng ký sang luồng thực thi nghiệp vụ, sử dụng hàm __setProperty và __P.
Thread Group 1 (Lưu biến toàn cục):
${__setProperty(global_auth_token,${login_token},)}
Thread Group 2 (Đọc biến toàn cục):
${__P(global_auth_token,)}
8. Xử lý ký tự xuống dòng trong Regular Expression
Khi dữ liệu response chứa ký tự xuống dòng làm hỏng việc bắt chuỗi, hãy dùng hàm escape:
${__unescape(\n)}
9. Tham số hóa số lượng Thread và thời gian chạy
Sử dụng thuộc tính hệ thống để điều khiển cấu hình từ dòng lệnh (CLI).
Threads: ${__P(concurrent_users,10)}
Duration: ${__P(test_duration,60)}
10. Mã hóa và giải mã Base64
Sử dụng các hàm có sẵn của JMeter Custom Functions hoặc Plugins:
Mã hóa:
${__base64Encode({"action":"verify"\,"token":"abc123"},encoded_request)}
Giải mã:
${__base64Decode(YWN0aW9uOnZlcmlmeQ==,decoded_response)}