【玩转 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 思路分析:这个题目的关键就是,按照正常来判断对应位置是否相等,如果不相等,那么就判…...
SpringBoot-17-MyBatis动态SQL标签之常用标签
文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…...
国防科技大学计算机基础课程笔记02信息编码
1.机内码和国标码 国标码就是我们非常熟悉的这个GB2312,但是因为都是16进制,因此这个了16进制的数据既可以翻译成为这个机器码,也可以翻译成为这个国标码,所以这个时候很容易会出现这个歧义的情况; 因此,我们的这个国…...
vscode里如何用git
打开vs终端执行如下: 1 初始化 Git 仓库(如果尚未初始化) git init 2 添加文件到 Git 仓库 git add . 3 使用 git commit 命令来提交你的更改。确保在提交时加上一个有用的消息。 git commit -m "备注信息" 4 …...
Lombok 的 @Data 注解失效,未生成 getter/setter 方法引发的HTTP 406 错误
HTTP 状态码 406 (Not Acceptable) 和 500 (Internal Server Error) 是两类完全不同的错误,它们的含义、原因和解决方法都有显著区别。以下是详细对比: 1. HTTP 406 (Not Acceptable) 含义: 客户端请求的内容类型与服务器支持的内容类型不匹…...
Java - Mysql数据类型对应
Mysql数据类型java数据类型备注整型INT/INTEGERint / java.lang.Integer–BIGINTlong/java.lang.Long–––浮点型FLOATfloat/java.lang.FloatDOUBLEdouble/java.lang.Double–DECIMAL/NUMERICjava.math.BigDecimal字符串型CHARjava.lang.String固定长度字符串VARCHARjava.lang…...
如何为服务器生成TLS证书
TLS(Transport Layer Security)证书是确保网络通信安全的重要手段,它通过加密技术保护传输的数据不被窃听和篡改。在服务器上配置TLS证书,可以使用户通过HTTPS协议安全地访问您的网站。本文将详细介绍如何在服务器上生成一个TLS证…...
Cloudflare 从 Nginx 到 Pingora:性能、效率与安全的全面升级
在互联网的快速发展中,高性能、高效率和高安全性的网络服务成为了各大互联网基础设施提供商的核心追求。Cloudflare 作为全球领先的互联网安全和基础设施公司,近期做出了一个重大技术决策:弃用长期使用的 Nginx,转而采用其内部开发…...
mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包
文章目录 现象:mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包遇到 rpm 命令找不到已经安装的 MySQL 包时,可能是因为以下几个原因:1.MySQL 不是通过 RPM 包安装的2.RPM 数据库损坏3.使用了不同的包名或路径4.使用其他包…...
Maven 概述、安装、配置、仓库、私服详解
目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...
Pinocchio 库详解及其在足式机器人上的应用
Pinocchio 库详解及其在足式机器人上的应用 Pinocchio (Pinocchio is not only a nose) 是一个开源的 C 库,专门用于快速计算机器人模型的正向运动学、逆向运动学、雅可比矩阵、动力学和动力学导数。它主要关注效率和准确性,并提供了一个通用的框架&…...

