作者:Mars酱
声明:文章由作者原创,欢迎转载,转载前请联系我!
Pre-request Script简介
Postman 有一个基于 Node.js 的强大运行时,它允许我们向请求和集合中添加动态行为。允许我们编写 API 测试、构建可以包含动态参数的请求、在请求之间传递数据等等。您可以添加两种情况下的 JavaScript 代码:
- 在请求发送到服务器之前,在“Pre-request Script”选项卡中编写预请求脚本;
- 收到响应后,在 “ Test”选项卡中编写测试脚本。
脚本的执行顺序
在 Postman 中,单个请求的脚本执行顺序如下所示:
- 预请求脚本将在发送请求之前执行;
- 测试脚本将在发送请求后执行;
对于集合中的每个请求,脚本将按以下顺序执行:
- 与集合关联的预请求脚本将在集合中的每个请求之前运行。
- 与文件夹关联的预请求脚本将在文件夹中的每个直接子请求之前运行。
- 与集合关联的测试脚本将在集合中的每个请求之后运行。
- 与文件夹关联的测试脚本将在文件夹中的每个直接子请求之后运行。
对于集合中的每个请求,脚本将始终按照以下层次结构运行:
集合级脚本(如果有)、文件夹级脚本(如果有)、请求级脚本(如果有)。
请注意,此执行顺序适用于预请求脚本和测试脚本。
准备工作及操作步骤
依照兄弟篇JMeter | BeanShell入门级编写 - 掘金 (juejin.cn)中的需求,这次使用Pre-request Script来实现,正文开始之前啰嗦一遍需要准备的数据:
- 密钥对(accessKeyId、key) 。密钥对由服务端发放,其中包含accessKeyId和key,其中accessKey相当于账号,key相当于密码用来加密使用;
- 客户端需要校验的卡号(cardNo) 。卡号我们不能使用同一张卡,因为模拟不同的用户,所以要准备一大批卡号;
- 随机数(nonceStr) 。防止伪造,因此在生成签名串的时候加入随机数,随机数可以是任意方式,比如:随机数字 + 随机字母、纯随机数字、纯随机字母等等;
- 时间戳(timestamp) 。作用同样是防止伪造,增加防伪造的难度;
- 签名(sign) 。发送给服务端用来比对是否合法请求;
1. 发送前的配置
先创建一个Collection,这个是包含多个request请求的集合,本次例子只有1个get请求,但是我们还是创建Collection,也方便和其他request测试作好区分和管理:
再在建立好的Collection下Add一个request:
再配置好请求方式、填写url、请求参数:
这里和JMeter的变量定义方式不同,在JMeter中使用的是${变量名}
的格式来声明,而Postman中是使用{{变量名}}
的格式。
上图中和JMeter一样,声明了{{nonceStr}}
、{{timestamp}}
、{{sign}}
三个变量,依次分别表示随机数、时间戳、签名。
2. 编写Pre-request Script
配置准备好了、请求参数也填写好了,变量也声明了,那么我们就需要编写核心的Pre-reqeust Script,把所需的参数填充到之前声明的变量中去:
/** author: Mars酱 */
//1. 随机数的生成函数,随机规则是16位长度的英文字符串
function getRandomString(len) {
let $chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz'
let maxLen = $chars.length
let randomStr = ''
for (let i = 0; i < len; i++) {
randomStr += $chars.charAt(Math.floor(Math.random() * maxLen ))
}
return randomStr
}
var nonceStr = getRandomString(16);
// 2. 时间戳函数
function getTimestamp(){
var time = new Date().getTime();
return time;
}
var timestamp = getTimestamp();
// 3. 获取请求路径中固定的参数,比如:accessKeyId
var params = pm.request.url.query; //获取接口入参
// console.log(params);
// 4. 拼接参数准备好签名字符串
var str = []
params.map(function(item) {
if(item["key"] == "sign" || item["value"] === ""){
// "==" ==宽松相等,隐性类型转换,值相等,返回true; "===" 严格相等,值和类型都相等,返回true
} else if(item["key"] == "nonceStr"){
str.push(item["key"] + "=" + nonceStr);
} else if(item["key"] == "timestamp"){
str.push(item["key"] + "=" + timestamp);
} else {
str.push(item["key"] + "=" + item["value"]);
}
})
// console.log(str);
// 5. 声明签名用的私钥key
var key = "e992fdbec7cd1eb2b1c6c8e07d4eea60";
// 6. 补充key到参数串中
var sign = str.sort().join("&")+ "&key=" + key;
// console.log(sign);
// 先清除之前的sign变量值
pm.environment.unset("sign");
// 设置签名
// 填充时间戳给声明的变量
pm.environment.set("timestamp", timestamp);
// 填充随机数给声明的变量
pm.environment.set("nonceStr", nonceStr);
// 7. MD5加密签名规格,并赋值给环境变量`sign`
pm.environment.set("sign", CryptoJS.MD5(sign).toString().toUpperCase());
编写界面完成之后的效果:
ok,配置url、编写Pre-request Script完成,我们准备发送get请求。
发送请求
点击按钮,发射!
响应结果
发送之后会有响应结果,展示效果如图:
1区:响应结果。正确请求后服务端返回给调用者的业务数据;
2区:控制台,发送请求拼接的变量是不是正确可以从这里查看到。
好了,看到这里已经完成了发送单个get请求时动态填充变量的方式了。
但是兄弟篇JMeter | BeanShell入门级编写 - 掘金 (juejin.cn)中的需求是不同的用户发送请求的。在JMeter中可以使用xls文件随机抽取卡号,在Pre-request Script怎么随机抽取呢?接着说
入门进阶操作
随机抽取卡号我没花时间寻找怎么做(应该也是可以使用外部文件的),只是简单在在Pre-request Script中增加了一个随机数,随机数用来从脚本的卡号数组中随机抽一张卡,然后填充到卡号变量中,因此,我改造了一下请求:
1. 声明卡号变量
把之前固定写死的卡号,改成{{cardno}}
变量,如下:
2. 修改Pre-request Script
在原来的脚本中声明卡号数组,并从中随机选取卡号,最后填充到{{cardno}}
变量中,增加的脚本如下:
// 1. 声明卡池数组
var cardnos = [
"4313000039491060",
"4313000021146570",
"4313000021153140",
"4301120069995630",
"4313000024416410",
"4301020029201620",
// .... 卡池
]
// 2. 随机抽取卡池中的卡片,随机算法忽略,只是简单模拟
function getRandomCardNo(){
let index = Math.floor(Math.random()*100+1);
if(index >= 100){
index = 98;
}
return cardnos[index];
}
var cardno = getRandomCardNo();
// 3. 填充到cardno变量
pm.environment.set("cardno", cardno);
发送1000次请求
现在卡片已经是随机抽取了,那么我们用Postman模拟发送1000次。单击创建的Collection节点,在界面中找到run按钮:
鼠标放上去之后会有“Run Collection”的提示语,单击之后界面如下:
Iterations:迭代次数。需要发送多少次请求;
Delay:延迟数。默认即可
配置好之后就开始发送了,完成之后会有结果提示:
我主要关注两个标签:
Passed:表示通过多少个请求;
Failed:表示失败多少个请求;
到此,使用Postman发送get请求已经完成。Postman提供了可以在请求脚本中使用的JavaScript API。pm 对象提供了测试请求和响应数据的功能,以下简单示例一下pm的常用方法。
Pre-request Script中pm对象的常用方法
pm.globals.unset("variable_key"); // 清除全局变量
pm.environment.unset("variable_key"); // 清除环境变量
pm.globals.get("variable_key"); // 获取全局变量
pm.variables.get("variable_key"); // 获取一个变量
pm.environment.get("variable_key"); // 获取环境变量
pm.sendRequest("https://postman-echo.com/get", function (err, response) {
console.log(response.json());
}); // 发送一个请求
pm.globals.set("variable_key", "variable_value"); // 设置环境变量
最后
在Pre-request Script中使用的md5加密是CryptoJS对象,但是并未import进来,其实crypto-js外部库已经被Postman引入,直接按照外部库的官方使用方式使用即可,后续将会介绍Postman的沙盒模式中内置的外部库。