jMeter 流水账

前段时间做 QA 的活儿, 一直在弄 jMeter, 用来测试后端服务. 做的不是 API 压测, 而是走 user journey, 所以还挺有意思的. (压测有啥意思啊...)

基本工作流程就是 1) 用 jMeter 抓包, 录 req, res; 2) 整理 req, res 提取出关键变量; 3) 处理一些特殊情况, 做 fallback, 好把 user journey 走完.

这个过程中 2) 最有意思. 我做的工作基本是看 api 返回结果, 然后看前端代码 (iPad 客户端, 用的 react native) 的处理逻辑, 模仿它的处理流程对数据做相应的操作, 然后发 request, 直到把 user journey 走到头.

之前这是一个 QA (称之为 z) 在做, 后来我接了. 然后我发现... 特么这 QA 根本没法做. 因为 QA 对后端 API (如果你知道后端 DAO 的格式, 你就知道数据结构长啥样) 以及前端数据操作 (你不知道 react native 代码里对后端来的数据怎么操作, 你怎么进行下一步, 发送 request?) 都不可能太了解, 也不大有临时去翻代码的耐心. 深深为 QA 还要做这个活感到亚历山大. 所以, 或许, 这就该是个 DEV 的工作 (一个前后端代码都写的 DEV). 你得了解数据流以及这个过程中的数据转化, 才能走完这 user journey.

我们的 z 在写 jMeter 的时候, 错误的用了 Java. 明显不对. 因为我们前后端数据都是 JSON, 用 Java 来操作 JSON 实在太麻烦了. (而且我早就没有了手写 Java 的勇气) jMeter 通过 JSR 223 (Java 脚本平台) 支持多种脚本来撰写测试逻辑, 大概有 Java, Groovy, BeanShell script, jexl (Java Expression Language), javascript. 我就不论证 javascript 怎么特别特别好, 特别适合我们的情况了. 都是友军衬托的好, Java 和 groovy 能用吗? beanshell 和 jexl 根本是历史遗留语言... Anyway, 我用了 javascript.

下面是流水账.


定义 pwd, 好加载 js 脚本文件, 在 User Defined Variables 加入 pwd: ${__BeanShell(import org.apache.jmeter.services.FileServer; FileServer.getFileServer().getBaseDir())}, 这样就能在 js sampler 里用:
load(vars.get("pwd") + "/js/utils.js") 加载相关的函数和变量.

一些 js snippets:

// vars 是 get 和 put, 刚开始用成了 set 害我好久不知道为啥值就是设置不进去...
vars.put("offset", (${__threadNum}-1)*${dealers_per_batch});

var numberOfCarPlates = parseInt(vars.get("car_plate_numbers_#"));
for (var i = 0; i < numberOfCarPlates; i++) {
    var car_plate_number = vars.get("car_plate_numbers_" + (i + 1));
    ...
}

var sa2carPlateNumbers = JSON.parse(vars.get("sa2carPlateNumbers")) || {};

vars.put("pre_inspection_maps", prev.getResponseDataAsString());

//
function jMeterPut(store, jmKey, jmValues) {
  store.put(jmKey + "_#", jmValues.length);
  for (var i = 0; i < jmValues.length; i++) {
    store.put(jmKey + "_" + (i + 1), jmValues[i]);
  }
}

JDBC Request snippets:

SELECT DISTINCT dealer_id
FROM user
  INNER JOIN user_group ON user.id = user_group.user_id
WHERE dms_user_id = 'PMT'
ORDER BY dealer_id
LIMIT ${dealers_per_batch} OFFSET ${offset};

SELECT dms_dealer_code
FROM outlet
WHERE id = '${dealer_id}'
LIMIT 1;

一些 one liner, 当变量使:

${__Random(17500000000,17501111111,telephone)}

${__javaScript('侧视'+'一二三四五六七八九十'[parseInt(Date.now()*Math.random())%10]+'甲乙丙丁戊己庚辛壬癸'[Date.now()%10],name)}

// 哪个方便用哪个, groovy 也不错
${__groovy(new Date().format("yyyy-MM-dd HH:mm:ss"),)}

${__javaScript(new Date(Date.now() - (24-8)*60*60*1000).toISOString())}

// 记得用 Function Helper 生成和测试这些 one liner, 但可惜
// function helper 不会帮你转义逗号, 你需要自己加
${__javaScript(var a=[];[1\,2\,3\,4\,5\,6\,7\,8\,9].forEach(function(i){return a.push("0"+i);});a=a.sort(function(){return Math.random() < 0.5;}).splice(0\,1+parseInt( Math.random()*9)).sort();JSON.stringify(a) ,)}

${__javaScript(var x=new Date(Date.now()+Math.random()*10*24*60*60*1000);x.setMinutes(0);x.setSeconds(0);x.setMilliseconds(0);x.toISOString(),)}

JSON extractor 如果只有一个变量, 不需要写 default value. 如果有多个变量, 则需要用 ; 号分隔, 而且必须要有 default value. 不然提取不出来.

jMeter 的变量都是 string, 所以不要往变量里面存 boolean 之类的数据类型, 请存入 "true" 和 "false" 字符串 (复合结构用 JSON.stringify, JSON.parse 来序列化). 用 If Controller 的时候, 也要使用 "${should_confirm}" === "true" 来做判断 (两边都有引号). 一些栗子:

  • "${selected_owner_id}" !=== ""
  • Math.random() > ${dos_event_threshold}
  • "true" === "false" (turn off controller)

Supplementary

执行顺序

变量和函数

http://jmeter.apache.org/usermanual/functions.html

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 200,302评论 5 470
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,232评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 147,337评论 0 332
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,977评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,920评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,194评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,638评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,319评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,455评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,379评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,426评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,106评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,696评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,786评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,996评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,467评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,043评论 2 341

推荐阅读更多精彩内容