当前位置: 首页 > news >正文

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

book cover for the 2nd version

《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 集合最终结构

【图 11.7 用于接口自动化测试的 Postman 集合最终结构】

3.1 测试环境的改造

根据前面的设计,下一步应该逐一输入每个接口的 URL、请求参数等等。为方便管理,应该将通用参数放到放到专门的测试环境中,其中包括:

  • base_url:从集合变量迁移到专门的环境中,便于统一管理;
  • task_id:待测试的单个待办项 ID。其值随着测试的进行,很可能不为 1;
  • CALL:这是两个版本中都有提及、却未能补充说明的一个神秘变量。经本人实测,它应该是为了实现请求方法(Method)的 动态切换 而专门设计的一个特殊变量,相当于解耦请求方法。例如按如下方式对 CALL 变量赋初值 GET

img11.19

CALL 变量的用法如下所示:

img11.20

不过,这种动态调用方式可能有违 Postman 接口测试最佳实践,在本书的两个版本中都没有做进一步说明。

关于测试环境的几点重要说明

  1. 对请求方法使用变量:经实测,在 Postman 的请求方法上使用变量时,

    1. 该变量名必须全部大写(CALL);
    2. 但是变量的值可以是小写(get / post 均可);
  2. 变量的初始值与当前值的区别:

    1. 根据书中观点,初始值仅用于给人们提供参考,使用时只用当前值(没说到点子上);
    2. 而根据 Postman 官方文档,初始值(Initial value)会同步到 Postman 服务器,因此不宜存放敏感信息。确需共享敏感信息,建议将其类型设为 secret
    3. 当前值(Current value)不会同步到 Postman 服务器,这些值仅在本地持久化,数据会相对安全些。
    4. 如果后期需要频繁使用敏感信息,建议还是将变量放入 vault 作用域,这样可实现加密存储,以确保敏感数据的安全性。例如:

    图 11.8 利用 Vault 级变量实现数据的加密存储,甚至可以限定域名,且不会同步到 Postman 服务器

    【图 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 变量

【图 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 包含数据清理逻辑的新增接口实测结果

【图 11.10 包含数据清理逻辑的新增接口实测结果】

为了验证上图中新增的 ID2 任务已被成功删除,可以再查一次列表:

图 11.11 测试完新增接口,再次调用查询接口,以验证新增接口中的数据清空逻辑是否生效(确已生效)

【图 11.11 测试完新增接口,再次调用查询接口,以验证新增接口中的数据清空逻辑是否生效(确已生效)】

最后还需要注意,在新增接口的 Authorization 标签中配置登录令牌,表示只有登录成功的用户才可新增待办事项:

图 11.12 根据获取到的 token 配置新增接口的鉴权类型

【图 11.12 根据获取到的 token 配置新增接口的鉴权类型】

3.5 对修改接口的测试

而对于修改接口 PUT /tasks/{{task_id}} 的测试,则需要先满足两个前提:

  • 用户已登录;
  • 已生成转为修改接口新增的测试数据;

第一项很好实现,直接配置 Authorization 标签即可。

第二项则需要先调新增接口,成功后再对临时新增的数据进行修改。怎样复用新增接口中的创建任务逻辑、同时又不触发新增接口中的测试脚本呢?

这里作者采用了一个非常巧妙的设计:在新增接口的测试脚本末尾,将当前请求直接存入一个环境变量(req):

pm.environment.set('req', pm.request)

实际效果如下图所示:

图 11.13 改造新增接口的测试逻辑,在末尾将本次请求直接存入变量 req 中

【图 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.14 包含提前新增数据的修改接口测试结果截图】

也可以在浏览器中查看修改结果:

图 11.15 从浏览器再次验证修改接口的测试逻辑(先新增一条,再进行修改。符合预期)

【图 11.15 从浏览器再次验证修改接口的测试逻辑(先新增一条,再进行修改。符合预期)】

3.6 对删除接口的测试

延用修改接口的测试思路,删除接口 DELETE /tasks/{{task_id}} 的测试流程设计如下:

  1. 配置 Authorization 鉴权选项;(与新增、修改接口一致)
  2. 发送请求前先新增一条临时数据,并将其 ID 更新到 task_id 变量中;(与修改接口一致)
  3. 执行删除后,检查响应码是否正常;
  4. 随即利用 task_id 调用单个实例的查询接口,验证是否删除成功。

首先配置登录令牌:

图 11.16 为删除接口配置登录令牌

【图 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 先新增、再删除、最后再查询验证的删除接口实测效果图

【图 11.17 先新增、再删除、最后再查询验证的删除接口实测效果图】

此外,也可以从线上的 GitPod 后台看到三次请求的日志信息:

图 11.18 从 GitPod 看到的删除接口实测日志信息截图

【图 11.18 从 GitPod 看到的删除接口实测日志信息截图】

4 测试集合的共享操作

4.1 分享 Postman 集合

公开分享

  • 将集合和环境移至公共工作区(public workspace)。
  • 生成公共链接或嵌入代码,方便他人访问。

注意事项

  • 确保不泄露敏感信息(如 API 密钥、内部数据)。
  • 遵循组织的安全政策。

备注

经本地实测,共享测试集合的操作非常简单,都是可视化的流程;只不过要是之前的工作区为 仅本人可见,则 Postman 会默认共享到某个小组,并让你输入组员帐号;否则需要先将该集合、环境移动到一个公共空间,再点共享:

img11.32

唯一需要注意的是,此前创建的私有模块、公共函数等脚本在共享时都将失效(私有模块暂不支持共享操作)。

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…...

深度分析:网站快速收录与网站内容多样性的关系

本文转自&#xff1a;百万收录网 原文链接&#xff1a;https://www.baiwanshoulu.com/87.html 网站快速收录与网站内容多样性之间存在着密切的关系。以下是对这一关系的深度分析&#xff1a; 一、网站内容多样性对快速收录的影响 提升搜索引擎抓取效率&#xff1a; 多样化的…...

feign 远程调用详解

在平常的开发工作中&#xff0c;我们经常需要跟其他系统交互&#xff0c;比如调用用户系统的用户信息接口、调用支付系统的支付接口等。那么&#xff0c;我们应该通过什么方式进行系统之间的交互呢&#xff1f;今天&#xff0c;简单来总结下 feign 的用法。 1&#xff1a;引入依…...

【Android】jni开发之导入opencv和libyuv来进行图像处理

做视频图像处理时需要对其进行水印的添加&#xff0c;放在应用层调用工具性能方面不太满意&#xff0c;于是当下采用opencvlibyuv方法进行处理。 对于Android的jni开发不是很懂&#xff0c;我的需求是导入opencv方便在cpp中调用&#xff0c;但目前找到的教程都是把opencv作为模…...

【Elasticsearch】terms聚合误差问题

Elasticsearch中的聚合查询在某些情况下确实可能存在误差&#xff0c;尤其是在处理分布式数据和大量唯一值时。这种误差主要来源于以下几个方面&#xff1a; 1.分片数据的局部性 Elasticsearch的索引通常被分成多个分片&#xff0c;每个分片独立地计算聚合结果。由于数据在分…...

深入理解 `box-sizing: border-box;`:CSS 布局的利器

深入理解 box-sizing: border-box;&#xff1a;CSS 布局的利器 默认行为示例代码 使用 box-sizing: border-box;示例代码 全局应用 box-sizing: border-box;示例代码 实际应用场景1. 表单布局2. 网格布局 总结 在 CSS 中&#xff0c;box-sizing 属性决定了元素的总宽度和高度是…...

【原子工具】快速幂 快速乘

题幂算.一切即1 阴阳迭变积微著&#xff0c;叠浪层峦瞬息功 莫道浮生千万事&#xff0c;元知万象一归宗 文章目录 快速幂原始快速幂&#xff08;O(logn)&#xff09;二分递归形式非递归形式 模下意义的快速幂&#xff08;O(logn)&#xff09;二分递归形式非递归形式 快速乘龟速…...

Apache SeaTunnel 整体架构运行原理

概述 SeaTunnel 缘起 数据集成在现代企业的数据治理和决策支持中扮演着至关重要的角色。随着数据源的多样化和数据量的迅速增长及业务需求的快速变化&#xff0c;企业需要具备强大的数据集成能力来高效地处理数据。SeaTunnel通过其高度可扩展和灵活的架构&#xff0c;帮助企业…...

Nginx如何实现 TCP和UDP代理?

文章目录 前言 Nginx之TCP和UDP代理 工作原理示意图 配置文件和命令参数注释 基本命令 配置实例说明 TCP代理实例UDP代理实例 总结 前言 Nginx是一个高性能的HTTP和反向代理服务器&#xff0c;同时也支持TCP/UDP代理。在1.9.13版本后&#xff0c;Nginx已经支持端口转发&…...

蓝桥杯思维训练营(三)

文章目录 题目详解680.验证回文串 II30.魔塔游戏徒步旅行中的补给问题观光景点组合得分问题 题目详解 680.验证回文串 II 680.验证回文串 II 思路分析&#xff1a;这个题目的关键就是&#xff0c;按照正常来判断对应位置是否相等&#xff0c;如果不相等&#xff0c;那么就判…...

Android LinearLayout、FrameLayout、RelativeLayout、ConstraintLayout大混战

一、为什么布局性能如此重要&#xff1f; 在Android应用中&#xff0c;布局渲染耗时直接决定了界面的流畅度。根据Google官方数据&#xff0c;超过60%的卡顿问题源于布局性能不佳。本文将彻底解析三大传统布局的性能奥秘&#xff0c;并提供可直接落地的优化方案。 二、三大布局…...

WPF技术体系与现代化样式

目录 ​​1 WPF技术架构解析​​ ​​1.1 技术演进与定位​​ ​​1.2 核心机制对比​​ ​​2 样式与资源系统​​ ​​2.1 资源(Resource)定义与作用域​​ ​​2.2 样式(Style)与触发器​​ ​​3 开发环境配置(.NET 8)​​ ​​3.1 安装流程​​ ​​3.2 项目结…...

Go语言学习-->项目中引用第三方库方式

Go语言学习–&#xff1e;项目中引用第三方库方式 1 执行 go mod tidy 分析引入的依赖有没有正常放在go.mod里面 找到依赖的包会自动下载到本地 并添加在go.mod里面 执行结果&#xff1a; 2 执行go get XXXX&#xff08;库的名字&#xff09;...

如何查看自己电脑安装的Java——JDK

开始->运行->然后输入cmd进入dos界面 &#xff08;快捷键windows->输入cmd&#xff09; 输入java -version&#xff0c;回车 出现了一下信息就是安装了jdk 输入java -verbose&#xff0c;回车 查看安装目录...

LangChain4j 学习教程项目

LangChain4j 学习教程 项目地址项目简介主要功能使用的技术和库项目环境配置环境要求 依赖版本每天学习内容和目标Day 01Day 02Day 03Day 04Day 05Day 06Day 07Day 08Day 09Day 10Day 11Day 12重点学习内容 RAG 经过为期12天&#xff08;日均1小时&#xff09;的LangChain4j源码…...

亚远景科技助力东风日产通过ASPICE CL2评估

热烈祝贺东风日产通过ASPICE CL2评估 近日&#xff0c;东风日产PK1B VCM热管理项目成功通过ASPICE CL2级能力评估&#xff0c;标志着东风日产在汽车电子软件研发管理体系及技术创新能力上已达到国际领先水平&#xff0c;为其全球化布局注入强劲动能。 ASPICE&#xff1a;国际竞…...

GaLore:基于梯度低秩投影的大语言模型高效训练方法详解一

&#x1f4d8; GaLore&#xff1a;基于梯度低秩投影的大语言模型高效训练方法详解 一、论文背景与动机 随着大语言模型&#xff08;LLM&#xff09;参数规模的不断增长&#xff0c;例如 GPT-3&#xff08;175B&#xff09;、LLaMA&#xff08;65B&#xff09;、Qwen&#xff…...

Vue.js教学第十八章:Vue 与后端交互(二):Axios 拦截器与高级应用

Vue 与后端交互(二):Axios 拦截器与高级应用 在上一篇文章中,我们学习了 Axios 的基本用法,包括如何发送不同类型的 HTTP 请求以及基本的配置选项。本文将深入剖析 Axios 的拦截器功能,探讨请求拦截器和响应拦截器的作用、配置方法和应用场景,通过实例展示如何利用拦截…...

32单片机——窗口看门狗

1、WWDG的简介 WWDG&#xff1a;Window watchdog&#xff0c;即窗口看门狗 窗口看门狗本质上是能产生系统复位信号和提前唤醒中断的递减计数器 WWDG产生复位信号的条件&#xff1a; &#xff08;1&#xff09;当递减计数器值从0x40减到0x3F时复位&#xff08;即T6位跳变到0&a…...

如何自定义一个 Spring Boot Starter?

导语&#xff1a; 在后端 Java 面试中&#xff0c;Spring Boot 是绕不开的重点&#xff0c;而“如何自定义一个 Starter”作为进阶开发能力的体现&#xff0c;常被面试官用于考察候选人的工程架构思维与 Spring Boot 底层掌握程度。本文将带你深入理解自定义 Starter 的实现逻辑…...