【玩转 Postman 接口测试与开发2_014】第11章:测试现成的 API 接口(下)——自动化接口测试脚本实战演练 + 测试集合共享

《API Testing and Development with Postman》最新第二版封面
文章目录
- 3 接口自动化测试实战
- 3.1 测试环境的改造
- 3.2 对列表查询接口的测试
- 3.3 对查询单个实例的测试
- 3.4 对新增接口的测试
- 3.5 对修改接口的测试
- 3.6 对删除接口的测试
- 4 测试集合的共享操作
- 4.1 分享 Postman 集合
- 4.2 使用 GitHub 展示
写在前面
终于来到了本章最激动人心的自动化测试实战环节了!用于演示的 ToDo App 项目看似功能简单,实则暗藏玄机。作者虽然只选了几个接口进行演示,但从仅有的几个典型脚本中也可以学到很多实战技巧,比如复用公共的测试逻辑、在当前请求中调用其他现成的接口、利用请求前后脚本实现“无痕测试”……这些精彩内容即便是第二次梳理依旧让人眼前一亮,值得每一位立志深耕 API 接口测试的长期主义者们反复推敲,用心体会。
(接上篇)
3 接口自动化测试实战
……最后给出的 Postman 测试集合结构如下:

【图 11.7 用于接口自动化测试的 Postman 集合最终结构】
3.1 测试环境的改造
根据前面的设计,下一步应该逐一输入每个接口的 URL、请求参数等等。为方便管理,应该将通用参数放到放到专门的测试环境中,其中包括:
base_url:从集合变量迁移到专门的环境中,便于统一管理;task_id:待测试的单个待办项 ID。其值随着测试的进行,很可能不为 1;CALL:这是两个版本中都有提及、却未能补充说明的一个神秘变量。经本人实测,它应该是为了实现请求方法(Method)的 动态切换 而专门设计的一个特殊变量,相当于解耦请求方法。例如按如下方式对CALL变量赋初值GET:

CALL 变量的用法如下所示:

不过,这种动态调用方式可能有违 Postman 接口测试最佳实践,在本书的两个版本中都没有做进一步说明。
关于测试环境的几点重要说明
对请求方法使用变量:经实测,在
Postman的请求方法上使用变量时,
- 该变量名必须全部大写(
CALL);- 但是变量的值可以是小写(
get/post均可);变量的初始值与当前值的区别:
- 根据书中观点,初始值仅用于给人们提供参考,使用时只用当前值(没说到点子上);
- 而根据
Postman官方文档,初始值(Initial value)会同步到Postman服务器,因此不宜存放敏感信息。确需共享敏感信息,建议将其类型设为secret;- 当前值(
Current value)不会同步到Postman服务器,这些值仅在本地持久化,数据会相对安全些。- 如果后期需要频繁使用敏感信息,建议还是将变量放入
vault作用域,这样可实现加密存储,以确保敏感数据的安全性。例如:
【图 11.8 利用 Vault 级变量实现数据的加密存储,甚至可以限定域名,且不会同步到 Postman 服务器】
3.2 对列表查询接口的测试
接口测试不宜大而全,而应该小步走、多迭代。
对于列表查询类接口 GET /tasks,可以先硬编码,然后再重构成较灵活的形式。例如先对第一个元素进行检查:
const tasks = pm.response.json();
const firstTask = {"id": 77,"description": "Learn API Testing","status": "Complete","created_by": "user1"
}
pm.test("Check first task data", function () { // Assume that the first task won't changepm.expect(tasks[0]).to.eql(firstTask);
});
上述测试存在明显硬伤:列表的第一个待办项很可能会变化。于是可以略作调整,由元素值绝对相等改为对 key 集的检查:
pm.test("Check that the first task has required fields", function () {const taskKeys = Object.keys(jsonData[0]);pm.expect(taskKeys).to.have.members(['id','description', 'status','created_by']);
});
3.3 对查询单个实例的测试
对于单个待办事项的查询接口 GET /tasks/{{task_id}},其测试逻辑与列表类似,都需要对目标对象的 key 集进行检查。这就涉及重复代码的共享,此时可以将通用脚本放到同一个 文件夹 的 Post-response 层。但示例项目的特殊性在于,列表返回的是一个集合对象(数组)、单个查询只返回一个元素,不能简单共享所有脚本。
此时就不能用文件夹共享脚本了,但可以利用 Postman 全新的私有仓库(package library)导出一个私有的 package 包,例如命名为 common-tests:
// in common-tests module
function checkTaskFields(task) {const taskKeys = Object.keys(task);pm.expect(taskKeys).to.have.members(['id', 'status', 'description', 'created_by']);
}
module.exports = {checkTaskFields
}// in Post-response tag
const { checkTaskFields } = pm.require('common-tests');const [task] = pm.response.json();
pm.test("Check first task field", function () {checkTaskFields(task);
});
3.4 对新增接口的测试
对于新增接口 POST /tasks,与查询接口最大的不同在于,出于测试目的新增的临时数据,需要在完成测试后及时清空,即调用删除接口。这样就需要先获取登录令牌。调用登录接口 POST /token 后,需将获取的令牌存入环境变量(例如 token):

【图 11.9 调用登录接口后,将获取的令牌存入 token 变量】
注意,这里的 token 作用域无论是集合层还是环境层都行,只是放到集合层的语义更好(测试环境可以指定给其他集合,容易引发不必要的冲突)。
这样新增接口就暗含一个前提:需要提前登录换取令牌(也很合理)。
于是,新增接口的测试脚本可以这样写:
const { checkTaskFields } = pm.require('common-tests');// check for task keys
const task = pm.response.json();
pm.test('Task has a id', function() {checkTaskFields(task);
});// clean up test data
const base_url = pm.environment.get('base_url');
const {id: task_id} = task;
const token = pm.environment.get('token');
const auth = {type: 'bearer',bearer: [{key: 'token',value: `${token}`,type: 'string'}]
};
pm.sendRequest({url: `${base_url}/tasks/${task_id}`,method: 'DELETE',auth
}, function(err, response) {if(err) {console.error(err);return;}pm.expect(response.status).to.eql('OK');
});
实测结果:

【图 11.10 包含数据清理逻辑的新增接口实测结果】
为了验证上图中新增的 ID 为 2 任务已被成功删除,可以再查一次列表:

【图 11.11 测试完新增接口,再次调用查询接口,以验证新增接口中的数据清空逻辑是否生效(确已生效)】
最后还需要注意,在新增接口的 Authorization 标签中配置登录令牌,表示只有登录成功的用户才可新增待办事项:

【图 11.12 根据获取到的 token 配置新增接口的鉴权类型】
3.5 对修改接口的测试
而对于修改接口 PUT /tasks/{{task_id}} 的测试,则需要先满足两个前提:
- 用户已登录;
- 已生成转为修改接口新增的测试数据;
第一项很好实现,直接配置 Authorization 标签即可。
第二项则需要先调新增接口,成功后再对临时新增的数据进行修改。怎样复用新增接口中的创建任务逻辑、同时又不触发新增接口中的测试脚本呢?
这里作者采用了一个非常巧妙的设计:在新增接口的测试脚本末尾,将当前请求直接存入一个环境变量(req):
pm.environment.set('req', pm.request)
实际效果如下图所示:

【图 11.13 改造新增接口的测试逻辑,在末尾将本次请求直接存入变量 req 中】
然后转到修改接口的 Pre-request 选项卡,读取 req 的值并通过脚本调用新增接口,新增结束后,再将任务 ID 更新到 task_id 中:
// use the 'Create a task' to create a task & set its task_id
pm.sendRequest(pm.environment.get('req'),function(err, resp) {if(err) {console.error(err);return;}const {id: task_id} = resp.json();pm.environment.set('task_id', task_id);}
)
最后切到 Post-response 选项卡,对修改后的内容进行测试:
pm.test('Description matches what was set', function() {const { description } = pm.response.json();pm.expect(description).to.eql('modified task')
});
实测效果:

【图 11.14 包含提前新增数据的修改接口测试结果截图】
也可以在浏览器中查看修改结果:

【图 11.15 从浏览器再次验证修改接口的测试逻辑(先新增一条,再进行修改。符合预期)】
3.6 对删除接口的测试
延用修改接口的测试思路,删除接口 DELETE /tasks/{{task_id}} 的测试流程设计如下:
- 配置
Authorization鉴权选项;(与新增、修改接口一致) - 发送请求前先新增一条临时数据,并将其 ID 更新到
task_id变量中;(与修改接口一致) - 执行删除后,检查响应码是否正常;
- 随即利用
task_id调用单个实例的查询接口,验证是否删除成功。
首先配置登录令牌:

【图 11.16 为删除接口配置登录令牌】
然后设置请求前脚本:
pm.sendRequest(pm.environment.get('req'),function(err, resp) {if(err) {console.error(err);return;}const { id: task_id } = resp.json();pm.environment.set('task_id', task_id);}
);
接着是删除请求响应后的测试脚本:
pm.test("Status code is 201 or 200", function () {pm.expect(pm.response.code).to.be.oneOf([200, 201]);
});const base_url = pm.environment.get('base_url');
const task_id = pm.environment.get('task_id');
pm.sendRequest({url: `${base_url}/tasks/${task_id}`,method: 'GET'
}, function(err, resp) {if(err) {console.error(err);return;}console.log(`resp.status: ${resp.status}`);pm.expect(resp.status).to.eql('Not Found');
});
实测结果如下:

【图 11.17 先新增、再删除、最后再查询验证的删除接口实测效果图】
此外,也可以从线上的 GitPod 后台看到三次请求的日志信息:

【图 11.18 从 GitPod 看到的删除接口实测日志信息截图】
4 测试集合的共享操作
4.1 分享 Postman 集合
公开分享:
- 将集合和环境移至公共工作区(public workspace)。
- 生成公共链接或嵌入代码,方便他人访问。
注意事项:
- 确保不泄露敏感信息(如 API 密钥、内部数据)。
- 遵循组织的安全政策。
备注
经本地实测,共享测试集合的操作非常简单,都是可视化的流程;只不过要是之前的工作区为 仅本人可见,则
Postman会默认共享到某个小组,并让你输入组员帐号;否则需要先将该集合、环境移动到一个公共空间,再点共享:
唯一需要注意的是,此前创建的私有模块、公共函数等脚本在共享时都将失效(私有模块暂不支持共享操作)。
4.2 使用 GitHub 展示
- 创建 GitHub 仓库:
- 上传
Postman集合和环境文件。 - 使用
Markdown编写文档,说明测试用例和运行方法。
- 上传
后记
虽然我本人不是专职测试,但自认对Postman也算比较了解了,学了这章内容后,感觉Postman还有很多彩蛋功能有待发掘。庆幸自己没有被前半章的冗余描述困住脚步,也没有想要敷衍了事的心态,否则就会和这本书的精华内容无缘了。既然要学,就得把整本书最难的部分给啃掉,不给后续的精进挖坑;毕竟坑挖多了迟早是要还的。
相关文章:
【玩转 Postman 接口测试与开发2_014】第11章:测试现成的 API 接口(下)——自动化接口测试脚本实战演练 + 测试集合共享
《API Testing and Development with Postman》最新第二版封面 文章目录 3 接口自动化测试实战3.1 测试环境的改造3.2 对列表查询接口的测试3.3 对查询单个实例的测试3.4 对新增接口的测试3.5 对修改接口的测试3.6 对删除接口的测试 4 测试集合的共享操作4.1 分享 Postman 集合…...
Linux03——常见的操作命令
root用户以及权限 Linux系统的超级管理员用户是:root用户 su命令 可以切换用户,语法:su [-] [用户名]- 表示切换后加载环境变量,建议带上用户可以省略,省略默认切换到root su命令是用于账户切换的系统命令ÿ…...
w188校园商铺管理系统设计与实现
🙊作者简介:多年一线开发工作经验,原创团队,分享技术代码帮助学生学习,独立完成自己的网站项目。 代码可以查看文章末尾⬇️联系方式获取,记得注明来意哦~🌹赠送计算机毕业设计600个选题excel文…...
leetcode——二叉树的最近公共祖先(java)
给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。 百度百科中最近公共祖先的定义为:“对于有根树 T 的两个节点 p、q,最近公共祖先表示为一个节点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的…...
基于FPGA的BT656编解码
概述 BT656全称为“ITU-R BT.656-4”或简称“BT656”,是一种用于数字视频传输的接口标准。它规定了数字视频信号的编码方式、传输格式以及接口电气特性。在物理层面上,BT656接口通常包含10根线(在某些应用中可能略有不同,但标准配置为10根)。这些线分别用于传输视频数据、…...
解锁数据结构密码:层次树与自引用树的设计艺术与API实践
1. 引言:为什么选择层次树和自引用树? 数据结构是编程中的基石之一,尤其是在处理复杂关系和层次化数据时,树形结构常常是最佳选择。层次树(Hierarchical Tree)和自引用树(Self-referencing Tree…...
本地快速部署DeepSeek-R1模型——2025新年贺岁
一晃年初六了,春节长假余额马上归零了。今天下午在我的电脑上成功部署了DeepSeek-R1模型,抽个时间和大家简单分享一下过程: 概述 DeepSeek模型 是一家由中国知名量化私募巨头幻方量化创立的人工智能公司,致力于开发高效、高性能…...
WAWA鱼2024年终总结,关键词:成长
前言 本来想着偷懒一下,不写2024年终总结了,因为24年上半年还在忙毕业,下半年在忙转正,其实没什么太多好写的。结果被an_da和学弟催更了,哈哈哈,感谢大家对我近况的关注,学校内容基本都忘的差不…...
使用VCS进行单步调试的步骤
使用VCS对SystemVerilog进行单步调试的步骤如下: 1. 编译设计 使用-debug_all或-debug_pp选项编译设计,生成调试信息。 我的4个文件: 1.led.v module led(input clk,input rst_n,output reg led );reg [7:0] cnt;always (posedge clk) beg…...
【Elasticsearch】硬件资源优化
🧑 博主简介:CSDN博客专家,历代文学网(PC端可以访问:https://literature.sinhy.com/#/?__c1000,移动端可微信小程序搜索“历代文学”)总架构师,15年工作经验,精通Java编…...
Elasticsearch 指南 [8.17] | Search APIs
Search API 返回与请求中定义的查询匹配的搜索结果。 http GET /my-index-000001/_search Request GET /<target>/_search GET /_search POST /<target>/_search POST /_search Prerequisites 如果启用了 Elasticsearch 安全功能,针对目标数据流…...
QT+mysql+python 效果:
# This Python file uses the following encoding: utf-8 import sysfrom PySide6.QtWidgets import QApplication, QWidget,QMessageBox from PySide6.QtGui import QStandardItemModel, QStandardItem # 导入需要的类# Important: # 你需要通过以下指令把 form.ui转为ui…...
Java 序列化和反序列化作用
Java 序列化和反序列化的核心作用是将对象转换为可存储或传输的字节流(序列化),以及从字节流恢复对象(反序列化)。以下是详细说明和示例: 作用 持久化存储 将对象保存到文件或数据库,重启后仍可…...
【4】阿里面试题整理
[1]. 介绍一下数据库死锁 数据库死锁是指两个或多个事务,由于互相请求对方持有的资源而造成的互相等待的状态,导致它们都无法继续执行。 死锁会导致事务阻塞,系统性能下降甚至应用崩溃。 比如:事务T1持有资源R1并等待R2&#x…...
回顾生化之父三上真司的游戏思想
1. 放养式野蛮成长路线,开创生存恐怖类型 三上进入capcom后,没有培训,没有师傅手把手的指导,而是每天摸索写策划书,老员工给出不行的评语后,扔掉旧的重写新的。 然后突然就成为游戏总监,进入开…...
Java循环操作哪个快
文章目录 Java循环操作哪个快一、引言二、循环操作性能对比1、普通for循环与增强for循环1.1、代码示例 2、for循环与while循环2.1、代码示例 3、循环优化技巧3.1、代码示例 三、循环操作的适用场景四、使用示例五、总结 Java循环操作哪个快 一、引言 在Java开发中,…...
Maven jar 包下载失败问题处理
Maven jar 包下载失败问题处理 1.配置好国内的Maven源2.重新下载3. 其他问题 1.配置好国内的Maven源 打开⾃⼰的 Idea 检测 Maven 的配置是否正确,正确的配置如下图所示: 检查项⼀共有两个: 确认右边的两个勾已经选中,如果没有请…...
【Numpy核心编程攻略:Python数据处理、分析详解与科学计算】1.25 视觉风暴:NumPy驱动数据可视化
1.25 视觉风暴:NumPy驱动数据可视化 目录 #mermaid-svg-i3nKPm64ZuQ9UcNI {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-i3nKPm64ZuQ9UcNI .error-icon{fill:#552222;}#mermaid-svg-i3nKPm64ZuQ9UcNI …...
Baklib推动数字化内容管理解决方案助力企业数字化转型
内容概要 在当今信息爆炸的时代,数字化内容管理成为企业提升效率和竞争力的关键。企业在面对大量数据时,如何高效地存储、分类与检索信息,直接关系到其经营的成败。数字化内容管理不仅限于简单的文档存储,更是整合了文档、图像、…...
读书笔记 | 《最小阻力之路》:用结构思维重塑人生愿景
一、核心理念:结构决定行为轨迹 橡皮筋模型:愿景张力的本质 书中提出:人类行为始终沿着"现状"与"愿景"之间的张力路径运动,如同橡皮筋拉伸产生的动力。 案例:音乐家每日练习的坚持,不…...
React中使用箭头函数定义事件处理程序
React中使用箭头函数定义事件处理程序 为什么使用箭头函数?1. 传递动态参数2. 避免闭包问题3. 确保每个方块的事件处理程序是独立的4. 代码可读性和维护性 示例代码总结 在React开发中,处理事件是一个常见的任务。特别是当我们需要传递动态参数时&#x…...
高阶开发基础——快速入门C++并发编程6——大作业:实现一个超级迷你的线程池
目录 实现一个无返回的线程池 完全代码实现 Reference 实现一个无返回的线程池 实现一个简单的线程池非常简单,我们首先聊一聊线程池的定义: 线程池(Thread Pool) 是一种并发编程的设计模式,用于管理和复用多个线程…...
少样本提示词模板
文章目录 少样本提示词模板 少样本提示词模板 少样本提示是一种基于机器学习的技术,利用少量的样本(即提示词的示例部分)来引导模型对特定任务进行学习和执行。这些示例能让模型理解开发者期望它完成的任务的类型和风格。在给定的任务中&…...
SQLGlot:用SQLGlot解析SQL
几十年来,结构化查询语言(SQL)一直是与数据库交互的实际语言。在一段时间内,不同的数据库在支持通用SQL语法的同时演变出了不同的SQL风格,也就是方言。这可能是SQL被广泛采用和流行的原因之一。 SQL解析是解构SQL查询…...
代码随想录算法训练营Day35
第九章 动态规划part03 正式开始背包问题,背包问题还是挺难的,虽然大家可能看了很多背包问题模板代码,感觉挺简单,但基本理解的都不够深入。 如果是直接从来没听过背包问题,可以先看文字讲解慢慢了解 这是干什么的。 …...
ECharts 样式设置
ECharts 样式设置 引言 ECharts 是一款功能强大的可视化库,广泛用于数据可视化。样式设置是 ECharts 中的重要一环,它能够帮助开发者根据需求调整图表的视觉效果,使其更加美观和易于理解。本文将详细介绍 ECharts 的样式设置,包…...
【腾讯前端面试】纯css画图形
之前参加腾讯面试,第一轮是笔试,面试官发的试卷里有一题手写css画一个扇形、一个平行四边形……笔试时间还是比较充裕的,但是我对这题完全没有思路😭于是就空着了,最后也没过。 今天偶然翻到廖雪峰大佬的博客里提到了关…...
DBeaver连接MySQL提示Access denied for user ‘‘@‘ip‘ (using password: YES)的解决方法
在使用DBeaver连接MySQL数据库时,如果遇到“Access denied for user ip (using password: YES)”的错误提示,说明用户认证失败。此问题通常与数据库用户权限、配置错误或网络设置有关。本文将详细介绍解决此问题的步骤。 一、检查用户名和密码 首先&am…...
截止到2025年2月1日,Linux的Wayland还有哪些问题是需要解决的?
截至2025年2月1日,Wayland需要解决的核心问题可按权重从高到低排序如下: 1. 屏幕共享与远程桌面的完整支持(权重:★★★★★) 问题:企业场景(如 腾讯会议)、开发者远程调试依赖稳定的屏幕共享功能。当前Wayland依赖PipeWire和XWayland,存在权限管理复杂、多显示器选择…...
【C++篇】位图与布隆过滤器
目录 一,位图 1.1,位图的概念 1.2,位图的设计与实现 1.5,位图的应用举例 1.4,位图常用应用场景 二,布隆过滤器 2.1,定义: 2.2,布隆过滤器的实现 2.3, 应…...

