【玩转 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 集合…...
前后端通过docker部署笔记
项目背景:这是一个SpringBootvue3的项目,通过maven打包后,需要在Linux服务器上部署,本篇博客主要记录docker-compose.yaml文件的含义: docker-compose.yml 文件中定义了一个 algorithm_platform_frontend 容器&#…...
五十天精通硬件设计第四天-场效应管知识及选型
场效应管(FET,Field-Effect Transistor)是一种利用电场效应控制电流的半导体器件,广泛应用于放大、开关等电路中。以下是场效应管的基本知识及选型要点: 一、场效应管的基本知识 1. 类型: - **结型场效应管(JFET)**: - N沟道和P沟道两种类型。 - 栅极与…...
了解 ALV 中的 field catalog (ABAP List Viewer)
在 ABAP 中,字段目录是使用 ALV (ABAP List Viewer) 定义内部表中的数据显示方式的关键元素。它提供对 ALV 中显示的字段的各种属性的控制,例如列标题、对齐方式、可见性、可编辑性等。关键概念: Field Catelog 字段目…...
【基于SprintBoot+Mybatis+Mysql】电脑商城项目之修改密码和个人资料
🧸安清h:个人主页 🎥个人专栏:【Spring篇】【计算机网络】【Mybatis篇】 🚦作者简介:一个有趣爱睡觉的intp,期待和更多人分享自己所学知识的真诚大学生。 目录 🎃1.修改密码 -持久…...
十一、CentOS Stream 9 安装 Docker
一、Docker 环境安装 1、软件源(仓库)信息 使用如下命令可列出当前系统配置的所有软件源(仓库)信息 # 列出所有软件源 dnf repolist 这表明系统有三个仓库 AppStream 、 BaseOS、Extras-Common 被启用 2、配置软件源镜像 使用如下命令可配置 Docker 软件包下载的镜像地址 …...
FreeRTOS学习 --- 中断管理
什么是中断? 让CPU打断正常运行的程序,转而去处理紧急的事件(程序),就叫中断 中断执行机制,可简单概括为三步: 1,中断请求 外设产生中断请求(GPIO外部中断、定时器中断…...
如何在Intellij IDEA中识别一个文件夹下的多个Maven module?
目录 问题描述 理想情况 手动添加Module,配置Intellij IDEA的Project Structure 问题描述 一个文件夹下有多个Maven项目,一个一个开窗口打开可行但是太麻烦。直接open整个文件夹会发现Intellij IDEA默认可能就识别一个或者几个Maven项目,如…...
机器学习模型--线性回归、逻辑回归、分类
一、线性回归 级别1:简单一元线性回归(手工实现) import numpy as np import matplotlib.pyplot as plt# 生成数据 X np.array([1, 2, 3, 4, 5]) y np.array([2, 4, 5, 4, 5])# 手动实现梯度下降 def gradient_descent(X, y, lr0.01, epo…...
gitlab个别服务无法启动可能原因
目录 一、gitlab的puma服务一直重启 1. 查看日志 2. 检查配置文件 3. 重新配置和重启 GitLab 4. 检查系统资源 5. 检查依赖和服务状态 6. 清理和优化 7. 升级 GitLab 8. 查看社区和文档 二、 gitlab个别服务无法启动可能原因 1.服务器内存或磁盘已满 2.puma端口冲突…...
react的antd表格数据回显在form表单中
1、首先为table添加编辑按钮 {title: 操作,align: center,render: (_: any, record: any) > (<div style{{ display: flex, alignItems: center, justifyContent: space-evenly }}><Buttonsize"small"onClick{() > deitor(record)} style{{ margin…...
深度分析:网站快速收录与网站内容多样性的关系
本文转自:百万收录网 原文链接:https://www.baiwanshoulu.com/87.html 网站快速收录与网站内容多样性之间存在着密切的关系。以下是对这一关系的深度分析: 一、网站内容多样性对快速收录的影响 提升搜索引擎抓取效率: 多样化的…...
feign 远程调用详解
在平常的开发工作中,我们经常需要跟其他系统交互,比如调用用户系统的用户信息接口、调用支付系统的支付接口等。那么,我们应该通过什么方式进行系统之间的交互呢?今天,简单来总结下 feign 的用法。 1:引入依…...
【Android】jni开发之导入opencv和libyuv来进行图像处理
做视频图像处理时需要对其进行水印的添加,放在应用层调用工具性能方面不太满意,于是当下采用opencvlibyuv方法进行处理。 对于Android的jni开发不是很懂,我的需求是导入opencv方便在cpp中调用,但目前找到的教程都是把opencv作为模…...
【Elasticsearch】terms聚合误差问题
Elasticsearch中的聚合查询在某些情况下确实可能存在误差,尤其是在处理分布式数据和大量唯一值时。这种误差主要来源于以下几个方面: 1.分片数据的局部性 Elasticsearch的索引通常被分成多个分片,每个分片独立地计算聚合结果。由于数据在分…...
深入理解 `box-sizing: border-box;`:CSS 布局的利器
深入理解 box-sizing: border-box;:CSS 布局的利器 默认行为示例代码 使用 box-sizing: border-box;示例代码 全局应用 box-sizing: border-box;示例代码 实际应用场景1. 表单布局2. 网格布局 总结 在 CSS 中,box-sizing 属性决定了元素的总宽度和高度是…...
【原子工具】快速幂 快速乘
题幂算.一切即1 阴阳迭变积微著,叠浪层峦瞬息功 莫道浮生千万事,元知万象一归宗 文章目录 快速幂原始快速幂(O(logn))二分递归形式非递归形式 模下意义的快速幂(O(logn))二分递归形式非递归形式 快速乘龟速…...
Apache SeaTunnel 整体架构运行原理
概述 SeaTunnel 缘起 数据集成在现代企业的数据治理和决策支持中扮演着至关重要的角色。随着数据源的多样化和数据量的迅速增长及业务需求的快速变化,企业需要具备强大的数据集成能力来高效地处理数据。SeaTunnel通过其高度可扩展和灵活的架构,帮助企业…...
Nginx如何实现 TCP和UDP代理?
文章目录 前言 Nginx之TCP和UDP代理 工作原理示意图 配置文件和命令参数注释 基本命令 配置实例说明 TCP代理实例UDP代理实例 总结 前言 Nginx是一个高性能的HTTP和反向代理服务器,同时也支持TCP/UDP代理。在1.9.13版本后,Nginx已经支持端口转发&…...
蓝桥杯思维训练营(三)
文章目录 题目详解680.验证回文串 II30.魔塔游戏徒步旅行中的补给问题观光景点组合得分问题 题目详解 680.验证回文串 II 680.验证回文串 II 思路分析:这个题目的关键就是,按照正常来判断对应位置是否相等,如果不相等,那么就判…...
uniapp 对接腾讯云IM群组成员管理(增删改查)
UniApp 实战:腾讯云IM群组成员管理(增删改查) 一、前言 在社交类App开发中,群组成员管理是核心功能之一。本文将基于UniApp框架,结合腾讯云IM SDK,详细讲解如何实现群组成员的增删改查全流程。 权限校验…...
装饰模式(Decorator Pattern)重构java邮件发奖系统实战
前言 现在我们有个如下的需求,设计一个邮件发奖的小系统, 需求 1.数据验证 → 2. 敏感信息加密 → 3. 日志记录 → 4. 实际发送邮件 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其…...
Keil 中设置 STM32 Flash 和 RAM 地址详解
文章目录 Keil 中设置 STM32 Flash 和 RAM 地址详解一、Flash 和 RAM 配置界面(Target 选项卡)1. IROM1(用于配置 Flash)2. IRAM1(用于配置 RAM)二、链接器设置界面(Linker 选项卡)1. 勾选“Use Memory Layout from Target Dialog”2. 查看链接器参数(如果没有勾选上面…...
《基于Apache Flink的流处理》笔记
思维导图 1-3 章 4-7章 8-11 章 参考资料 源码: https://github.com/streaming-with-flink 博客 https://flink.apache.org/bloghttps://www.ververica.com/blog 聚会及会议 https://flink-forward.orghttps://www.meetup.com/topics/apache-flink https://n…...
ip子接口配置及删除
配置永久生效的子接口,2个IP 都可以登录你这一台服务器。重启不失效。 永久的 [应用] vi /etc/sysconfig/network-scripts/ifcfg-eth0修改文件内内容 TYPE"Ethernet" BOOTPROTO"none" NAME"eth0" DEVICE"eth0" ONBOOT&q…...
Typeerror: cannot read properties of undefined (reading ‘XXX‘)
最近需要在离线机器上运行软件,所以得把软件用docker打包起来,大部分功能都没问题,出了一个奇怪的事情。同样的代码,在本机上用vscode可以运行起来,但是打包之后在docker里出现了问题。使用的是dialog组件,…...
html css js网页制作成品——HTML+CSS榴莲商城网页设计(4页)附源码
目录 一、👨🎓网站题目 二、✍️网站描述 三、📚网站介绍 四、🌐网站效果 五、🪓 代码实现 🧱HTML 六、🥇 如何让学习不再盲目 七、🎁更多干货 一、👨…...
基于Java Swing的电子通讯录设计与实现:附系统托盘功能代码详解
JAVASQL电子通讯录带系统托盘 一、系统概述 本电子通讯录系统采用Java Swing开发桌面应用,结合SQLite数据库实现联系人管理功能,并集成系统托盘功能提升用户体验。系统支持联系人的增删改查、分组管理、搜索过滤等功能,同时可以最小化到系统…...
MySQL 知识小结(一)
一、my.cnf配置详解 我们知道安装MySQL有两种方式来安装咱们的MySQL数据库,分别是二进制安装编译数据库或者使用三方yum来进行安装,第三方yum的安装相对于二进制压缩包的安装更快捷,但是文件存放起来数据比较冗余,用二进制能够更好管理咱们M…...
STM32HAL库USART源代码解析及应用
STM32HAL库USART源代码解析 前言STM32CubeIDE配置串口USART和UART的选择使用模式参数设置GPIO配置DMA配置中断配置硬件流控制使能生成代码解析和使用方法串口初始化__UART_HandleTypeDef结构体浅析HAL库代码实际使用方法使用轮询方式发送使用轮询方式接收使用中断方式发送使用中…...

