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

Postman 学习笔记 II:测试、断言与变量管理

Postman 学习笔记 II:测试、断言与变量管理

上一篇笔记地址在:Postman 学习笔记 I:基础操作与请求管理

这一篇会涉及到一些简单的测试的功能,具体的 repo 还是在下面:

https://github.com/GoldenaArcher/postman-api-study

GH 中里面补了一些 collection 的东西,然后修改了一下 swagger 文档

目前 postman 系列的笔记都写完了,现在正在慢慢整理中,同时再重新进行 GraphQL 的学习——这一会儿会以一个比较工程化的角度去进行学习

测试

其实 UI 还是有一些修改的,现在 pre-req 和 post-req 都放在了 scripts 下面:

之前则是分开来的,另一个可以注意一下的是 console 部分,这里可以展开,这样请求看的就比较直接明显:

⚠️:postman 的所有请求都是共用一个 console 的,即 request1 发送完后,会在 console 输出请求的 URL,request2 发送完后,会在同一个 console 中输出结果

snippet

这算是 postman 本身的优点吧,它有一个快捷键可以一键调出一些比较常用的测试脚本:

如:

pm.test("Status code is 200", function () {pm.response.to.have.status(200);
});

这样可以做一个基础测试,搭配其他的脚本写起来比较方便。特别是在跑 runner 的时候,大批量 API 测试失败时,可以比较直观的看到是 endpoint 失效——即 status code 测试都失败,而不是其他原因

pm.test("Status code is 200", function () {pm.response.to.have.status(200);
});// 真正的测试
pm.test("Status value is ok", function () {var jsonData = pm.response.json();pm.expect(jsonData.status).to.eql("ok");
});

效果如下:

⚠️:postman 中拿到的数据还是字符串,所以需要用 pm.response.json() 转换成 JS 对象

其他的语法

一些比较常见的 code snippets:

const response = pm.response.json();pm.test("Status is OK", () => {pm.expect(response.status).to.be.oneOf(["ok", "OK"]);
});pm.test("Response is an object", () => {pm.expect(response).to.be.an("object");
});pm.test("Product name", () => {pm.expect(response.name).to.be.a("string");
});pm.test("Product in stock", () => {pm.expect(response.inStock).to.be.true;
});pm.test("Product price", () => {pm.expect(response.price).to.be.a("number");pm.expect(response.price).to.be.greaterThan(0);
});

处理错误案例

⚠️:这里用 mock server 的话,需要把 prefer: code=401 加到 header 获取 error case

有些时候需要处理 error cases,比如说故意不传 access token 去验证 auth,或者是传错误的参数去测试后端数据,这时候后端会传回非 200 的 code,这时候可以用下面的方法去测试这种 error cases:

pm.test("Status code is 401", function () {pm.response.to.have.status(401);
});

跑出来的结果是成功的:

collections 中其实也可以写测试,页面布局和 endpoint 是一样的,如果所有的 cases 返回的结果都类似——如都是成功或是失败,必须要登录,包含对应的 headers 等,那么其实可以把对应的 code snippets 放到 collections 中,而不是在每个测试中重复相同的代码

to.have hack

有的时候去要做 partial string match——这种情况下可以使用 .to.have.string() 去做 partial match,比如:

const response = pm.response.json();pm.test("Status code is 400", () => {pm.expect(response.code).to.eql(400);
});pm.test("Error message", () => {pm.expect(response.message).to.have.string("Invalid category. Must be one of");
});

这样可以检测 query param 传的是不合法的值,但是并不需要做完整的匹配,这样也不用担心后端 enum 的变化

断言及比较

上面提到了 to.have hack,这个语法看起来有点眼熟……?是的,因为本质上来说 postman 内部使用了一些 chai 的功能,也因此它暴露了一些这样的语法让开发/测试使用。除了 chai 之外,postman 同样也包含了 lodash,因此,下面的功能就能够比较轻松的实现了:

  • 深全等判断
    这里用的是 lodash 的 isEqual 和 chai 的 deep.equal 去做对比

    const lodash = require("lodash");const actual = pm.response.json();
    const expected = [{id: 4643,category: "coffee",name: "Starbucks Coffee Variety Pack, 100% Arabica",inStock: true,price: 29.99,},{id: 1234,category: "bread-bakery",name: "Freshly Baked Croissant",inStock: true,price: 3.99,},
    ];pm.test("deep equal (chai)", () => {pm.expect(actual).to.deep.equal(expected);
    });pm.test("deep equal (lodash)", () => {pm.expect(lodash.isEqual(actual, expected)).to.be.true;
    });
    

  • 部分匹配
    这种情况适合做部分匹配,如你知道数据库中包含数据 A,但是因为数据库的变动,db id,updatedAt, updatedBy 这种数据可能会变化
    这种情况下就比较适合做部分匹配,而不是深等

    const lodash = require("lodash");const items = pm.response.json();const mustHave = {category: "bread-bakery",name: "Freshly Baked Croissant",
    };pm.test("array contains an item matching subset", () => {const matched = _.some(items, (it) => lodash.isMatch(it, mustHave));pm.expect(matched, "should contain required subset").to.be.true;
    });
    

  • 数组比较

  • 嵌套对象比较

总体来说,如果可以搭配 lodash 和 chai 使用的话,postman 的测试也可以说是进行得比较深入了。只不过受限于工具的使用,代码复用会变得比较的困难

documentation

docs 的页面如下:

这部分的内容我其实用的不是很多,之前和现在的两个项目用的都是 swagger,postman 一直以来都是用来 ping 后端数据的

目前学习到的部分是:

  • description 可以用 markdown 编写
  • 自动生成请求参数,如 headers,path parameters
  • 可以生成自动 docs
    这个部分比较 tricky,要在 collection 首页进入:

    随后查看:

    这个文档还可以 publish,不过这个功能我没怎么研究过……
  • 可以自动生成 specifications

变量

这里的变量指的是 postman 的变量,即存在于 global、collection、environment、local 中的变量

下面的设置、获取、清理只需要替换对应的 scope 即可,除了 local,local 层直接使用 pm.variables.method() 去进行管理

postman 的权重为:local > data > environment > collection > global,其他的几个比较直观,data 暂时没有涉及到,这是来自 Runner / Newman 运行时传入的 CSV/JSON 数据,这要在自动化和 batch 操作的时候才会提到了

设置变量

语法如下:

pm.collectionVariables.set("firstName", "test");

其中 firstName 为变量名, test 为值

⚠️:这个操作实际上会修改 collection 中的变量,而 collection 中的变量一旦被修改了,则是会影响所有使用当前变量的成员。换言之,以 accessToken 为例,如果多个用户都在同时使用 postman,那么登录功能就会受到影响,特别是 accessToken 与 role 深度绑定的情况

这种情况多发生在 multi-tenant 和/或 多权限管理 的情况,如,成员 A 需要测试商家 A,成员 B 需要测试商家 B;或成员 A 需要测试管理员,成员 B 需要测试普通权限等

🧐  目前来说,只是针对 postman 这个工具而言,并没有什么特别好的解决方案。使用 pm.variables 将数据存在无法进行跨 API 的交流——这也是常规的流程,在登陆后使用 accessToken 去访问其他 API。使用 collections/environment 就会造成污染,使用 global 则很难做到同步和统一管理。目前来说可用的解决方案就是每个成员 fork 一下 collection,然后使用自己的独立环境进行开发,再定期监控主 collection 的变化,多次 fork 了……

讲了一些 downside,这里说下具体的使用方法——除了 accessToken 的用法:

const response = pm.response.json();pm.test("At least one available product exists", () => {pm.expect(response).to.be.an("array");pm.expect(response.length).to.be.greaterThan(0);pm.collectionVariables.set("productId", response[0].id);
});

这种实现的优势主要有:

  1. 可以自动获取现存的 productId,不用担心数据库中 id 的变化导致后续测试失败

  2. 使用 array ,并对其长度进行断言

    这种情况下,当 products 没有返回任何的数据,从测试中就能直观地判断出来。如果直接使用 pm.collectionVariables.set('productId', response[0].id); 的话,当 products 的长度为 0 时,下一步测试 single product 就会因为 null 值报错。那个时候再去判断哪里出了问题,就比较费时费力

  3. 测试可以比较方便的进行 extend,如这里只是对 array 和长度进行了断言。如果有需要的话,也可以对 product 进行断言,测试数据结构是否有变化

    不过类似操作,写在 collections 中会比较方便进行管理

获取变量

调用的方法也很简单,将 set 换成 get 即可:

pm.test("Correct product was retrieved", () => {pm.expect(response.id).to.equal(pm.collectionVariables.get("productId"));
});

清空变量

这里的清空会直接清空整个 scope 中的所有变量,所以需要慎用,语法为:pm.scope.unset('varName') ,如 pm.collectionVariables.unset('varName')

environment

environment 是一个可以更加动态的管理变量的 scope,搭配和 collection/workspaces 使用,可以统一/固定/规范化不同的环境,但是仍旧使用相同的变量

UI 操作如下:

环境是独立于 collection/workspace 的管理,因此可以单独进行 import/export——如果要使用不同的环境,如 local/dev/staging/prod 这种,也需要单独进行导入导出,它不与 collection/workspace 进行绑定

cookies

这里主要讲一下获取方式,即 pm.cookies.get("session_id") ,这个搭配断言比较好用

set cookie 比较的特殊,语法如下:

pm.cookies.jar().set(pm.request.url, "session_id", "mock-123456");

在使用 cookie 之前,需要将网址加入 allowlist 中,官方文档参考地址在:add domains to the allowlist,如果没有加入到 allowlist 中会出现访问失败的情况——我也遇到过这种情况,debug 了很久……

headers

headers 分为 request 和 response,调用方式为 pm.request.headerspm.response.headers ,除了 setget 之外,还有 has 这个调用方式

这个用的还是比较少的,request headers 可能会用的稍微多一些——这个值可以在 pre-script 的阶段进行修改

http://www.dtcms.com/a/398547.html

相关文章:

  • electron设置默认应用程序
  • Flink 初体验10 分钟完成下载、安装、本地集群启动与示例作业运行
  • toLua[二] Examples 01_HelloWorld分析
  • asp源码打开网站网站页面数量
  • 安卓手机termux安装ubuntu被kill进程解决
  • java后端工程师进修ing(研一版‖day48)
  • 目标检测进化史
  • 北京做养生SPA的网站建设高端网站建设 来磐石网络
  • 网站建设有哪三部来年做那些网站能致富
  • 外贸公司网站素材产品营销文案
  • VSCode C/C++ 开发环境配置
  • FPGA自学笔记--VIVADO RAM IP核控制和使用
  • 电源——设计DCDC原理图与参数选型
  • 企业网站建设策划书 前言263云通信官方网站
  • pip config list输出为空?如何配置pip镜像源?不同方式配置有什么区别?
  • 表格工具怎么选,国产化替代方案测评(2025 全维度实测版)
  • 分布式 ID 生成方案实战指南:从选型到落地的全场景避坑手册(二)
  • 企业网站建设案例宝安三网合一网站建设
  • 做透水砖的网站vs2019可以做网站吗
  • 鸿蒙后台定时任务实战
  • 【win32】ffmpeg 解码器2
  • MCU知识体系
  • 【win32】ffmpeg 解码器
  • 东莞市官网网站建设公司中企动力z邮箱登录入口
  • wordpress网站seo罗夫曼三大社区模式
  • 搭建一个属于自己的mac摄像头视频流rtsp服务
  • Spring Boot 集成 RabbitMQ 实现可靠消息传递:从配置到实战
  • Linux学习记录--多线程共享变量
  • 网站格式有哪些内容私人建设手机网站
  • 【Java后端】SpringBoot 常用工具类和工具方法汇总