使用 Postman 进行 API 测试
使用 Postman 进行 API 测试
前言
虽然之前分享过 RestAssured 进行接口测试的教程,但实践起来,会有阻碍:研发同学还是对 Postman 更熟悉,更倾向于使用 Postman 调试接口,而不是写 Java 代码对 Controller 层进行测试。
而笔者在针对旧的 Java 项目添加接口测试时,又遇到了另一个问题:那就是由于模块依赖,进行接口测试时,还在把旧的测试代码一并带上。虽然说有办法解决,但究竟是麻烦不断。
还有就是,Java 的类型检查,在写接口测试时十分束缚手脚。如下述代码:
// 为什么不设置 Map<String, String> ?
// 因为 menu 有个字段的类型是 Integer,使用 String 接收运行时会报错。
Optional<Map<String, Object>> foundMenu = menuList.stream().filter(v -> {
String code = (String) v.get("name"); // 这种类型转换代码实在多余!
return code.contains("管理员");
}).findFirst();
笔者实在忍不住吐槽了一番:
笔者思前想后,最终还是放弃测试代码要与源码使用统一技术栈的构想,再次搬出 Postman 作为接口自动化测试的工具。
本地调试
接口集合
新建一个 collection,然后再在里面新建接口。
新建方法多种多样,可以手工新建,也可以 curl 导入,也可以从 swagger 导入。
从 cURL 导入
对于已经上线的接口,使用 cURL 导入非常方便,省去了拼接参数的过程。
下面以获取 token 接口为例进行说明。
打开登录页面,打开浏览器控制台(按 F12),点击登录按钮,找到获取 token 的接口,然后右键 -> Copy -> Copy as cURL(bash)。
再打开 Postman,点击 Import 即可导入接口。
环境变量
点击右上角红框处,即可设置变量,需要先设置环境名。
一般设置 current value 即可,则运行 postman 时使用的就是该值。
如果有多套环境,就点击复制,再修改环境名及包含变量的 current value 即可。
使用 {{var}}
的形式引用变量,可在 url 及 body 处引用环境变量 var
。
注意细节,如果是变量值是字符串,要用双引号把它包起来:
{
"name": "exist",
"version": 1,
"datasourceTypeId": {{datasourceTypeId}}, // 这个是数字
"fileId": "{{fileId}}", // 这个是字符串
}
Postman内置了全局变量,输入 {{
会出现提示:
使用示例:
{
"name": "my_name_{{$timestamp}}"
}
环境变量还可以在测试用例里去修改值:
请求设置
对于请求体的发送,一般进行如下设置:
还可以利用 Pre-request Script, 在请求前动态修改请求设置。
比如有以下场景:
- 线上环境接口路径为:/app-name/api/v1/api-name
- 本地环境接口路径为:/v1/api-name,也即线上环境接口地址多了两个前缀
观察请求在 Postman 中的数据结构如下:
则可以编写前置脚本如下:
if (pm.environment.name.includes("local")) {
pm.request.url.path.shift()
pm.request.url.path.shift()
}
接口测试
编写用例
在 Tests 标签页里,即可编写测试,在 SNIPPETS 里会有相应的示例。
下面给出常用CRUD相关接口的测试用例代码:
- 设置 jwt
pm.test('Response status code is 200', function () {
pm.response.to.have.status(200);
resp = pm.response.json()
pm.environment.set('jwt', "Bearer " + resp.payload.access_token)
})
- 设置当天时间:
pm.environment.set('currentDate', new Date().toISOString().split('T')[0]);
- 创建
pm.test("Status code is 200", function () {
pm.response.to.have.status(200);
const resp = pm.response.json();
pm.expect(resp.code == "0").to.be.true // 如果报错,后面就不会执行
pm.expect(resp.payload.name == "新增").to.be.true
pm.environment.set("id", resp.payload.id)
});
- 修改
pm.test("Status code is 200", function () {
pm.response.to.have.status(200);
const resp = pm.response.json();
pm.expect(resp.code == "0").to.be.true
});
- 查询
pm.test("Status code is 200", function () {
pm.response.to.have.status(200);
const resp = pm.response.json();
pm.expect(resp.code == "0").to.be.true
pm.expect(resp.payload.length > 0).to.be.true
});
- 删除
pm.test("Status code is 200", function () {
pm.response.to.have.status(200);
const resp = pm.response.json();
pm.expect(resp.code == "0").to.be.true
});
- 确保返回的数据里没有特定的数据
pm.test("Status code is 200", function () {
pm.response.to.have.status(200);
let payload = pm.response.json().payload;
let found = payload.content.some(v => v.username.includes('unwanted'))
pm.expect(found).to.be.false;
});
上传文件
如果要上传文件,则一般进行如下设置:
注意要把文件放到工作目录中。查看工作目录的方法如下:
把要上传的文件放到该目录下:
这样才方便后续运行集合、以及持续集成。
运行集合
本地调试好了,把代码部署到线上环境后,就可以使用 postman 对线上的接口进行测试了。
先切换到对应的环境,再重置变量当前值
再选择集合,点击 Run collection:
点击运行,可以看到集合内所有接口的执行结果:
提示:如果单独调试成功,运行集合却失败,注意检查文件是否已保存。如果文件处于编辑未保存状态,运行集合时使用的是修改前的接口。
持续集成
导出接口
导出接口合集:
使用推荐的格式,导出一个 json 文件。
导出环境变量
也是导出一个 json 文件。
复制要上传的文件
把要上传的文件,复制到项目根目录。
如果没有上传文件的接口,忽略此步骤。
提交到Git
把导出的 json 文件放到项目根目录中(与上传文件同级),并提交到 Git
建立CI任务
以 Gitlab 为例,修改.gitlab-ci.yml
,增加以下内容:
newman:
stage: test
image: node:lts
script:
- node -v
- npm -v
- npm install -g newman
- newman run export.postman_collection.json -e dev.postman_environment.json --reporter-cli-exit-code
tags:
- your-gitlab-runner #记得把这里修改成你的 runner 名字
only:
- /dev|test|uat/
推送代码,即可看到流水线
结果如下: