【玩转 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 change
    pm.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 还有很多彩蛋功能有待发掘。庆幸自己没有被前半章的冗余描述困住脚步,也没有想要敷衍了事的心态,否则就会和这本书的精华内容无缘了。既然要学,就得把整本书最难的部分给啃掉,不给后续的精进挖坑;毕竟坑挖多了迟早是要还的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/964559.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

登录认证(5):过滤器:Filter

统一拦截 上文我们提到(登录认证(4):令牌技术),现在大部分项目都使用JWT令牌来进行会话跟踪,来完成登录功能。有了JWT令牌可以标识用户的登录状态,但是完整的登录逻辑如图所示&…

基于Spring Security 6的OAuth2 系列之七 - 授权服务器--自定义数据库客户端信息

之所以想写这一系列,是因为之前工作过程中使用Spring Security OAuth2搭建了网关和授权服务器,但当时基于spring-boot 2.3.x,其默认的Spring Security是5.3.x。之后新项目升级到了spring-boot 3.3.0,结果一看Spring Security也升级…

git基础使用--1--版本控制的基本概念

文章目录 git基础使用--1--版本控制的基本概念1.版本控制的需求背景,即为啥需要版本控制2. 集中式版本控制SVN3. 分布式版本控制 Git4. SVN和Git的比较 git基础使用–1–版本控制的基本概念 1.版本控制的需求背景,即为啥需要版本控制 先说啥叫版本&…

< OS 有关 > Android 手机 SSH 客户端 app: connectBot

connectBot 开源且功能齐全的SSH客户端,界面简洁,支持证书密钥。 下载量超 500万 方便在 Android 手机上,连接 SSH 服务器,去运行命令。 Fail2ban 12小时内抓获的 IP ~ ~ ~ ~ rootjpn:~# sudo fail2ban-client status sshd Status for the jail: sshd …

课题推荐——基于自适应滤波技术的多传感器融合在无人机组合导航中的应用研究

无人机在现代航空、农业和监测等领域的应用日益广泛。为了提高导航精度,通常采用多传感器融合技术,将来自GPS、惯性测量单元(IMU)、磁力计等不同传感器的数据整合。然而,传感器的量测偏差、环境干扰以及非线性特性使得…

【MySQL】常用语句

目录 1. 数据库操作2. 表操作3. 数据操作(CRUD)4. 高级查询5. 索引管理6. 用户与权限7. 数据导入导出8. 事务控制9. 其他实用语句注意事项 如果这篇文章对你有所帮助,渴望获得你的一个点赞! 1. 数据库操作 创建数据库 CREATE DATA…

基于多智能体强化学习的医疗AI中RAG系统程序架构优化研究

一、引言 1.1 研究背景与意义 在数智化医疗飞速发展的当下,医疗人工智能(AI)已成为提升医疗服务质量、优化医疗流程以及推动医学研究进步的关键力量。医疗 AI 借助机器学习、深度学习等先进技术,能够处理和分析海量的医疗数据,从而辅助医生进行疾病诊断、制定治疗方案以…

使用 Elastic Cloud Hosted 优化长期数据保留:确保政府合规性和效率

作者:来自 Elastic Jennie Davidowitz 在数字时代,州和地方政府越来越多地承担着管理大量数据的任务,同时确保遵守严格的监管要求。这些法规可能因司法管辖区而异,通常要求将数据保留较长时间 —— 有时从一年到七年不等。遵守刑事…

【NLP 20、Encoding编码 和 Embedding嵌入】

目录 一、核心定义与区别 二、常见Encoding编码 (1) 独热编码(One-Hot Encoding) (2) 位置编码(Positional Encoding) (3) 标签编码(Label Encoding) (4) 注意事项 三、常见Embedding词嵌入 (1) 基础词嵌入…

【Envi遥感图像处理】010:归一化植被指数NDVI计算方法

文章目录 一、NDVI简介二、NDVI计算方法1. NDVI工具2. 波段运算三、注意事项1. 计算结果为一片黑2. 计算结果超出范围一、NDVI简介 归一化植被指数,是反映农作物长势和营养信息的重要参数之一,应用于遥感影像。NDVI是通过植被在近红外波段(NIR)和红光波段(R)的反射率差异…

7、怎么定义一个简单的自动化测试框架?

定义一个简单的自动化测试框架可以从需求理解、框架设计、核心模块实现、测试用例编写和集成执行等方面入手,以下为你详细介绍: 1. 明确框架需求和范围 确定测试类型:明确框架要支持的测试类型,如单元测试、接口测试、UI 测试等…

web-XSS-CTFHub

前言 在众多的CTF平台当中,作者认为CTFHub对于初学者来说,是入门平台的不二之选。CTFHub通过自己独特的技能树模块,可以帮助初学者来快速入门。具体请看官方介绍:CTFHub。 作者更新了CTFHub系列,希望小伙伴们多多支持…

Linux中的基本指令(二)

一、移动和重命名指令mv 1.1基本作用及使用规范 基本作用是进行文件的移动和重命名,使用规范如: mv src[目录/文件]dst[路径/文件] 回车 1.2三种不同的作用 通过在src部分和dst部分写入不同的内容,来实现文件的移动和重命名的等不同功能…

【RL Latest Tech】安全强化学习(Safe RL):理论、方法与应用

📢本篇文章是博主强化学习(RL)领域学习时,用于个人学习、研究或者欣赏使用,并基于博主对相关等领域的一些理解而记录的学习摘录和笔记,若有不当和侵权之处,指出后将会立即改正,还望谅…

qt-Quick笔记之Dark Mode And Light Mode In Application

qt-Quick笔记之Dark Mode And Light Mode In Application code review! 文章目录 qt-Quick笔记之Dark Mode And Light Mode In Application1.运行2.目录结构3.main.qml4.main.cpp5.main.pro6.main.qrc 本例修改自视频教程:Qt QML | 🌙 Dark Mode And ☀…

visual studio安装

一、下载Visual Studio 访问Visual Studio官方网站。下载 Visual Studio Tools - 免费安装 Windows、Mac、Linux 在主页上找到并点击“下载 Visual Studio”按钮。 选择适合需求的版本,例如“Visual Studio Community”(免费版本)&#x…

基于Springboot框架的学术期刊遴选服务-项目演示

项目介绍 本课程演示的是一款 基于Javaweb的水果超市管理系统,主要针对计算机相关专业的正在做毕设的学生与需要项目实战练习的 Java 学习者。 1.包含:项目源码、项目文档、数据库脚本、软件工具等所有资料 2.带你从零开始部署运行本套系统 3.该项目附…

【C++篇】位图与布隆过滤器

目录 一,位图 1.1,位图的概念 1.2,位图的设计与实现 1.5,位图的应用举例 1.4,位图常用应用场景 二,布隆过滤器 2.1,定义: 2.2,布隆过滤器的实现 2.3, 应…

GESP2023年12月认证C++六级( 第三部分编程题(1)闯关游戏)

参考程序代码&#xff1a; #include <cstdio> #include <cstdlib> #include <cstring> #include <algorithm> #include <string> #include <map> #include <iostream> #include <cmath> using namespace std;const int N 10…

list容器(详解)

list的介绍及使用&#xff08;了解&#xff0c;后边细讲&#xff09; 1.1 list的介绍&#xff08;双向循环链表&#xff09; https://cplusplus.com/reference/list/list/?kwlist&#xff08;list文档介绍&#xff09; 1. list是可以在常数范围内在任意位置进行插入和删除的序…