上次Postman 入门1 我们介绍全局变量和环境变量时已经使用过Tests 和 pre-request script 模块,但未细讲。这里我们就针对这个模块讲解一些常用的操作。
Script
Postman 提供了便捷的可视化界面操作,也提供了强大的脚本支持。Postman运行过程是基于强大的 Node.js,可以在请求发起前(Pre-request Script)和拿到请求返回后(Tests),通过编写JavaScript来实现请求间数据传递,请求参数动态生成等等。
Postman 名词定义
Pre-request Script 和 Tests 可以在集合(Collections)、夹(Folder)、请求(Request)中设置。估计大家可能会有个疑问,集合、夹、请求都只是指啥,这里补充一张图了解下Postman定义的名词,也算对上次分享的一个补充。
脚本执行顺序
在Postman中,单个请求的脚本执行顺序如下:
- 请求里的pre-request script 将在 Request 发起之前执行
- 请求里的Tests 将在Response 获取之后执行
对于一个集合里的请求,将按一下顺序执行
集合pre → 夹pre → 请求pre → Request → Response → 集合Tests → 夹Tests → 请求Tests
注意:集合夹中的Pre-quest script 和 Tests script 是每个Request请求之前和Response之后都会执行一次
知道执行顺序和执行次数,平时在使用这模块时根据具体场景合理应用便可。
了解Scprit大体作用后,我们来看几个常见场景,以及常见脚本编写。
Tests
场景1:API间参数传递
集合下所有API 请求发起都需要一个token或uid一类的字段,而这个字段可以由登录后从response获取。那么如果我们不充分利用好Tests,那么我们测试调用时往往需要先执行下 Login 然后拷贝 uid,接着修改要发起请求的uid字段,再发起请求,这样一个集合下如果有几十个API ,那么我们可能需要黏贴修改 N个API的uid字段,这非常麻烦。
正确做法,在login API的Tests 中编写个脚本以达到,Login请求拿到Response后往环境变量和全局变量写入一个变量供其他API使用。
例如Login API 返回大体如下的Json
{
"code": 1,
"content": {
"userId": "123123"
},
"msg": "成功",
"uid": "7a57ea7b-19cd-1234-1234-fa1be9ff045d1557562660436",
}
为了获得uid的值,并写入环境变量,我们可以在Tests 中加入如下脚本
// 把reponse 的body转成Json
let jsonData = JSON.parse(responseBody);
// 解析获得Json中的 uid
let uid = jsonData.uid;
// 设置一个环境变量 uid 值为 json解析获取到的值
pm.environment.set("uid", uid);
这时发起这个登录请求后,我们就会看到对应的环境变量中增加了一个 uid 环境变量,那么同集合里其他需要uid的API只需要在需要的位置添加 {{uid}} 便可以获取到最新的uid值
场景2:Response校验
通过Postman 测试API时,除了肉眼去看结果返回值,我们还可以在Tests中编写一些脚本用于校验我们的response。
例如还是Login接口,Login response和场景1是一样的,我们想校验接口返回的数据、状态和请求时间等。我们可以在Tests编写如下脚本:
pm.test("Response time is less than 200ms", function () {
// 获取请求时间,并校验小于200ms
pm.expect(pm.response.responseTime).to.be.below(200);
});
pm.test("Status code is 200", function () {
// 获取请求状态码,并校验是否为 200
pm.response.to.have.status(200);
});
pm.test("json test", function () {
// 获取response json
var jsonData = pm.response.json();
// 校验msg的值为 成功
pm.expect(jsonData.msg).to.eql("成功");
// 校验 status 为 1
pm.expect(jsonData.content.status).to.eql(1);
});
我们看看更多Response的属性,当然这些Response熟悉不适用与下面的pre-request script:
responseHeaders[String] {Object}:获取response的头部信息,添加String参数则获取指定的头部信息。但官方不推荐这么使用,更推荐使用postman.getResponseHeader(‘xxx’)。
console.log(responseHeaders) console.log(responseHeaders['Content-Type']) console.log(postman.getResponseHeader('Content-Type'))
responseCookies {Array}:返回一个数组,可以通过postman.getResponseCookie(cookieName) 获取具体的cookie信息。
- responseBody {string}:返回响应正文文本的字符串。可以用JSON.parse()转成数组。
- responseTime {number}:返回响应时间,单位ms
- responseCode[String] {Object}:返回的状态码,不带参数会返回4个属性。 常用的属性是 code 就是状态码。
console.log(responseCode)
console.log(responseCode['code'])
更多常用Tests脚本解释
- 设置环境变量
pm.environment.set("variable_key", "variable_value");
- 获取环境变量
pm.environment.get("variable_key");
- 清除环境变量
pm.environment.unset("variable_key");
- 设置全局变量
pm.globals.set("variable_key", "variable_value");
- 获取全局变量
pm.globals.get("variable_key");
- 清除全局变量
pm.globals.unset("variable_key");
- 获取一个变量:这个将从环境变量和全局变量中搜索变量,优先从环境变量中搜索
pm.variables.get("variable_key");
- 发起一个请求:
pm.sendRequest("https://postman-echo.com/get", function (err, response) {
console.log(response.json());
});
- 检查response body是否包含某个字符串
pm.test("Body matches string", function () {
pm.expect(pm.response.text()).to.include("string_you_want_to_search");
});
- 检查response body是否等于某个字符串
pm.test("Body is correct", function () {
pm.response.to.have.body("response_body_string");
});
- 检查JSON值
pm.test("Your test name", function () {
var jsonData = pm.response.json();
pm.expect(jsonData.value).to.eql(100);
});
- 校验某结果类型是否存在:如下是说response header包含Content-Type
pm.test("Content-Type is present", function () {
pm.response.to.have.header("Content-Type");
});
- 响应时间小于200毫秒
pm.test("Response time is less than 200ms", function () {
pm.expect(pm.response.responseTime).to.be.below(200);
});
- 状态代码是200
pm.test("Status code is 200", function () {
pm.response.to.have.status(200);
});
- 校验某对象是否包含某个字符串:例如下面校验response的body 包含 msg 属性
pm.test("Body is correct", function () {
pm.response.to.have.body("msg");
});
- 校验结果在某范围中:如下校验请求状态码是201,202
pm.test("Successful POST request", function () {
pm.expect(pm.response.code).to.be.oneOf([201,202]);
});
- 将XML主体转换为JSON对象:
var jsonObject = xml2Json(responseBody);
pre-request script
场景3:自定义变量
Postman尽管提供了不少的变量,但是有时这些变量均无法满足我们的需求。 例如创建用户API,我们需要一个11位并且1开头的不重复的电话号码。例如某API有个时间参数,我们需要传入当前日期等等。 那么这些我们就可以通过pre-request script 中通过编写简单的JS,使可支持。
// 生成10为随机数
function ronNum(){
let num = "";
for(let i=0;i<10;i++){
num +=Math.floor(Math.random()*10)
}
console.log(num)
return num;
}
// 生成1开头的11位随机数
let phoneNo ="1"+ronNum();
// 设置成环境变量供API引用
pm.environment.set("phone", phoneNo);
// 生成 xxxx-xx-xx格式日期
let date = new Date().getFullYear()+"-"+((new Date()).getMonth()+1)+"-"+(new Date()).getDate();
// 设置成date 环境变量
pm.environment.set("date", date);
场景4:接口依赖
例如调用删除API,你们为了避免我们每次删除都有效,这时我们往往在删除之前先调用一下添加的接口,这时我们可以再pre-request script中编写个调用add的API,先生成一条数据。在例如假设我们调用API前我们需要需要查阅数据库(假设我们已经提供了数据库交互的API),那么我们也可以把调用数据库API的步奏放于pre-request script。
// 调用 请求
pm.sendRequest("https://postman-echo.com/get", function (err, response) {
// 输出 reponse
console.log(response.json());
});
// 登陆 请求
pm.sendRequest({
url: "http://admin{{env}}.com/luckyadminweb/checkLogin.do_",
method: "POST",
header: {
"Content-Length": "1",
"Content-Type": "application/x-www-form-urlencoded"
},
body: {
mode: 'urlencoded',
urlencoded: [
{key: "username", value: "user1"},
{key: "password", value: "password1"}
]
},
function (err, res) {
console.log(res);
}
});
更多常用pre-request script脚本解释
跟Tests脚本类似,除了Response相关的不支持外,基本都支持。
Postman 内置支持库
Postman 现在不仅仅支持原生是JavaScript ,Postman 提供的 沙箱(Sandbox)里面还包含了如下库:
- Lodash:JS实用程序库
- cheerio:jQuery子集,提供更快速,精简的API(4.6.0及更高版本中提供)
- BackboneJS 不推荐使用:提供简单的模型,视图和集合。这将在未来版本的沙箱中删除。
- SugarJS 不推荐使用:使用有用的方法扩展本机JS对象。这将在未来版本的沙箱中删除。
- tv4 JSON模式验证器:针对json-schema草案的v4,用于验证JSON对象
- CryptoJS:标准和安全的加密算法。支持的算法:AES,DES,EvpKDF,HMAC-MD5,HMAC-SHA1 / 3/256/512,MD5,PBKDF2,Rabbit,SHA1 / 3/224/256/512,TripleDES
以上库不需要导出便可直接使用,Postman 桌面版还提供了 require。
require(moduleName:String):function → *
通过该requie还可以使用如下面模块。
- ajv → v6.6.2
- atob → v2.1.2
- btoa → v1.2.1
- chai → v4.2.0
- cheerio → v0.22.0
- crypto-js → v3.1.9-1
- csv-parse/lib/sync → v1.2.4
- lodash → v4.17.11 (when used with require, the inbuilt
_
object is for v3.10.1) - moment → v2.22.2 (sans locales)
- postman-collection → v3.4.0
- tv4 → v1.3.0
- uuid → (the module loaded is a shim for original module)
- xml2js → v0.4.19
例如 chai 模块为例看个demo:
// 导入 chai 模块
const chai = require('chai')
const assert = chai.assert;
pm.test("chai test", function () {
// 校验
assert.equal("abc", "abc");
});
Runner
Postman 带有Runner功能,用于批量运行脚本,但是在运行过程中如果集合中某个API调用失败,则剩下API的也将停止运行。
该功能主要有两种用途,一种是逐个运行某个集合下的多个API;另一种是针对某个或某场景API采用数据驱动的方式运行,这个常用于批量造数据。
界面介绍
入口
常用两个入口一个是直接Heade bar中的Runner按钮,一个是对应集合或者夹中的Run 按钮。
界面介绍
Collection or folder
通过这个选择要运行的集合或者文件夹。运行顺序从上到下。
Environment
选择运行时使用的环境变量
Iterations
迭代器用于设置集合运行的次数
Delay
设置运行中每个请求之间的时间间隔,单位毫秒
Log responses
设置集合运行时的响应日志记录。
- For all requests:所有请求的reponse都记录
- For failed requests:只显示失败的reponse记录
- For no requests:都不显示reponse记录
Data
为运行的集合API提供外部数据,支持text、csv和json的格式文件。
Persist variables
默认集合运行中任何环境变量的更改都不会反映到外部的请求构建器中。勾选起来则会替换外部构建器中的环境变量。
批量运行
- 选取一个集合
- 选择环境变量
- 设置每个请求间隔时间(可不设置)
- 点击 Run
- 运行界面可以查看每个请求的信息(如果Log Response设置为For no requests)则看不到任何的请求返回
数据驱动方式运行
数据驱动方式除了用于批量测试等价类的测试用例,更常用于通过接口批量造数据。例如我需要10个订单,那么我可以创建个下订单的集合,并在集合从上而下编写下订单过程需要调用的API,并做好接口间的数据传递。
下面我们就以批量测试等价类用例为例子讲解,批量造数据也是类似做法无非过程时常需要调用多个接口罢了。
假设有如下一个登录接口,我需要用不同的账号密码测试登录。
- 那么第一步我们可以本地创建一个Json或者csv文件,设定username和password两个字段,并设置要运行的测试值:
- csv
- json
[ { "userName": "u1", "password": "p1" }, { "userName": "u2", "password": "p2" }, { "userName": "u3", "password": "p3" } ]
- 设置请求参数,通过{{变量名}}获取文件中的参数值
- Runer运行,设定Data,选择你的csv或json文件后会自动帮你统计出 Iterrations,并可以通过Preview 预览数据源
- 点击run,可以结果页面看到我们一个api发起了3次请求,并每次请求都从数据源拿去一条对应的数据。