Nếu bạn chỉ có nhu cầu 1 thread – 1 row thì chỉ cần sử dụng CSV Data Set Config nhưng nếu bạn cần đọc 1 thread – xxx rows thì bạn phải code thôi. Code như thế nào thì bạn đọc bài dưới đây, có rất nhiều kiến thức cần học.
Nội dung bài viết
I. Ví dụ bài toán cụ thể
Bạn có 1 API, body của API là 1 json, json đó có chứa 1 mảng của 3 objects giống nhau cấu trúc. Data của 3 object này lại nằm trong 1 file csv mà mỗi object là 1 row.
Body của API:
[ { "key1": "12.6", "key2": "12.7", "key3": "12.43", "key4": "12.49", "key5": "12.43" }, { "key1": "12.69", "key2": "12.5", "key3": "12.34", "key4": "12.64", "key5": "12.45" }, { "key1": "12.43", "key2": "12.44", "key3": "12.45", "key4": "12.38", "key5": "12.6" } ]
File test.csv
12.6,12.7,12.43,12.49,12.43 12.69,12.5,12.34,12.64,12.45 12.43,12.44,12.45,12.38,12.6 12.51,12.55,12.43,12.45,12.35 12.38,12.56,12.48,12.46,12.42 12.68,12.44,12.42,12.65,12.62 12.29,12.58,12.37,12.49,12.44 12.69,12.57,12.41,12.5,12.35 12.34,12.59,12.38,12.49,12.34 12.29,12.49,12.39,12.34,12.63 12.5,12.54,12.37,12.45,12.51 12.44,12.45,12.5,12.49,12.64 12.66,12.45,12.64,12.61,12.53 12.54,12.61,12.37,12.55,12.66 12.4,12.52,12.45,12.46,12.55
II. Cách giải
- Step 1: Tạo test plan với SetUp Thread Group và Thread group
- Step 2: Chuyển file csv thành 1 List các object và lưu List vào trong 1 biến.
- Step 3: Từ List lấy ra đoạn object cần thiết, rồi tạo thành JSON.
Step 1: Tạo test plan
- SetUp Thread Group mục đích là để đọc file csv 1 lần duy nhất và nó sẽ không ảnh hưởng đến performance của Thread Group chính.
Number of Threads
phải nhỏ hơn hoặc bằng tổng số rows CSV / số rows muốn lấy. Ví dụ: File csv có 15 rows, muốn lấy 3 rows mỗi lần, thìNumber of Threads
<= 5- Loop count chỗ này đặt bao nhiêu cũng được, ko ảnh hưởng.
Step 2: Chuyển file csv thành 1 List
Mình sử dụng JSR223 Sampler
def payload = [] (1) new File('path_to_file/test.csv').readLines().eachWithIndex { line, index -> def entries = line.split(',') (2) def entry = [:] (3) entry.put('key1', entries[0]) (4) entry.put('key2', entries[1]) entry.put('key3', entries[2]) entry.put('key4', entries[3]) entry.put('key5', entries[4]) payload.add(entry) (5) } log.info(payload.toString()) (6) props.put('payload', payload) (7)
- (1): Tạo 1 List rỗng
- (2): Đọc từng dòng trong file csv, mỗi dòng lại biến thành 1 List, các item của List được tách ra bởi dấu phẩy.
- (3) Tạo ra 1 map rỗng
- (4) đẩy từng phần tử ở List nhỏ (bước 2) vào trong map
- (5) lưu từng map vào List (bước 1)
- (6) print thử List ra console xem đã lấy được thông tin chưa
- (7) Lưu List này vào trong 1 biến của Property. Vì để share được biến trong các Thread Group thì biến đó phải ở dạng Property
Đây là dòng log ở console, bước số 6, cấu trúc giống hệt csv.
2022-04-03 07:59:17,477 INFO o.a.j.m.J.JSR223 PreProcessor: [ [key1:12.6, key2:12.7, key3:12.43, key4:12.49, key5:12.43], [key1:12.69, key2:12.5, key3:12.34, key4:12.64, key5:12.45], [key1:12.43, key2:12.44, key3:12.45, key4:12.38, key5:12.6], [key1:12.51, key2:12.55, key3:12.43, key4:12.45, key5:12.35], [key1:12.38, key2:12.56, key3:12.48, key4:12.46, key5:12.42], [key1:12.68, key2:12.44, key3:12.42, key4:12.65, key5:12.62], [key1:12.29, key2:12.58, key3:12.37, key4:12.49, key5:12.44], [key1:12.69, key2:12.57, key3:12.41, key4:12.5, key5:12.35], [key1:12.34, key2:12.59, key3:12.38, key4:12.49, key5:12.34], [key1:12.29, key2:12.49, key3:12.39, key4:12.34, key5:12.63], [key1:12.5, key2:12.54, key3:12.37, key4:12.45, key5:12.51], [key1:12.44, key2:12.45, key3:12.5, key4:12.49, key5:12.64], [key1:12.66, key2:12.45, key3:12.64, key4:12.61, key5:12.53], [key1:12.54, key2:12.61, key3:12.37, key4:12.55, key5:12.66], [key1:12.4, key2:12.52, key3:12.45, key4:12.46, key5:12.55] ]
Step 3: Từ List lấy ra đoạn object cần thiết, rồi tạo thành JSON
Mình sử dụng JSR223 Pre-Processor, đặt tên là Get 3 rows
def start = ctx.getThreadNum()*3; (1) def end = start + 3; (2) def payload = props.get("payload") (3) def body = payload.subList(start,end) (4) vars.put('body', new groovy.json.JsonBuilder(body).toPrettyString()) (5)
- (1) Từ biến
ctx
lấy thông tin của thread number hiện tại, nếu là thread số 1 thìctx.getThreadNum()
= 0, lưu vào biếnstart
- (2) Từ biến
start
cộng thêm 3 để được biếnend
- (3) Lấy cái List ở Step 2 vào lưu vào biến
payload
,payload
bây giờ chính là cái List to đùng ở phía trên - (4) Từ List, cắt lấy 1 phần mình mong muốn theo
start
vàend
, Ví dụ:subList(0,3)
sẽ lấy được 3 rows đầu tiên,subList(3,6)
sẽ lấy được 3 rows tiếp theo - (5) Biến 3 rows trên thành 1 JSON array, sau đó Lưu JSON array vào biến
body
, chỗ này chỉ là biến đơn thuần, ko phải Property.
Và ở trên Jmeter UI, bạn chỉ cần khai báo theo cú pháp ${variable_name}
Ở đây mình có thêm cả biến ${__threadNum}
để show thread number lên View Result Tree, Ví dụ: Thread 1 sẽ lấy 3 dòng đầu tiên.
Thread 2 sẽ lấy 3 dòng tiếp theo
III. Tổng kết
Đây là 1 yêu cầu tương đối khó, nó đòi hỏi phải code và vững kiến thức rất nhiều chỗ trong Jmeter dưới đây:
- SetUp Thread Group
- JSR223 Sampler, Pre-Processor: code groovy
- Biến bình thường (vars) và biến Property (props)
- Cách save và get biến trong script và trên Jmeter UI.
Sample Test Plan ở đây, Lưu ý:
- Bạn phải cài Plugin Manager và Dummy Sampler Plugin trước
- Dùng Java 11 trở xuống, Java 17 chưa được support đầy đủ.