Cách đọc nhiều rows file csv trong jmeter

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.

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ến start
  • (2) Từ biến start cộng thêm 3 để được biến end
  • (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 startend, 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 ý:

0 0 votes
Article Rating
Subscribe
Notify of
guest
0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments