自学内容网 自学内容网

【玩转 Postman 接口测试与开发2_005】第六章:Postman 测试脚本的创建(上)

book cover for the 2nd version

《API Testing and Development with Postman》最新第二版封面

前言
本篇为原书第六章自学笔记的上篇。因为本章内容实在过于炸裂,且我在实测环节发现很多 Bug,特此跳过前面的基础知识,直接来到这一章帮作者修订一下书中存在的问题。至于跳过的第 3 至 5 章,等更新完这章内容再另行补上。特此说明。

第六章 Postman 测试脚本的创建

本章概要

  • 检查 API 接口响应
  • 设置预请求脚本(pre-request scripts)
  • Postman 环境(environments)的用法

6.0 概述

如果某个测试脚本运行了很长时间都从没出现过故障,那么不排除脚本本身在写法上可能有问题,例如一些低级断言错误:true === true5 === 5 等。

设计良好的测试套件也可能因为糟糕的断言脚本而功败垂成。

所谓 断言(assertion),即测试中检查实际结果是否符合预期的校验逻辑。

Postman 的测试脚本是基于 JavaScript 实现的,并内置了 Chai.js 断言库,可以对请求的 Header 头信息及 body 正文进行断言校验。

本章介绍这些断言的基本写法与用法,并结合 Collection Runner 工具介绍在测试套件层面(即 Collection 集合)自动运行多个请求的具体操作。

相关资源链接:详见 GitHub 第六章文件夹

6.1 检查 API 接口响应

示例项目:电影《星球大战》API 接口(集合名称:Star Wars API – Chapter 6)。

相关 JSON 配置文件 Star Wars API_Chapter6_initial.postman_collection.json 详见百度网盘:

  • 链接地址:https://pan.baidu.com/s/1cbc8hFxzi2g08egDVU8XAw
  • 提取码:yo47

导入配置后,点击 Postman 右上角的 Variables 图标查看变量声明情况,会看到预先定义的基础 URL 变量 base_url

图 6.1 导入演示项目后看到的预定义变量 base_url

【图 6.1 导入演示项目后看到的预定义变量 base_url】

然后将初始请求 Get People 的 URL 由 https://swapi.dev/api/people/1 替换为 {{base_url}}/people/1 就完成了环境搭建。

接着找到 Get People 下的 Scripts 标签,选中左边的 Post-response 选项卡,在脚本编辑区插入一段 Postman 内置的测试用例,例如验证响应码为 200 的示例代码:

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

实测执行情况如下(左下角表示断言已通过):

图 6.2 执行修改后的 Get People 请求得到的响应结果与测试结果截图

【图 6.2 执行修改后的 Get People 请求得到的响应结果与测试结果截图】

6.1.1 关于 pm.test 方法

测试脚本中的 pm.test 方法,即与绝大多数测试框架中的 test 方法用法一致,其中的 pm 指代 Postman,是一个全局对象,用于访问 请求响应 中的数据,或者访问 变量Cookie 等。而 test 方法接收一个描述信息字符串和一个回调函数;前者用于说明测试用例的意图,后者为具体的测试校验逻辑。pm.test() 方法在 Postman 中的签名为:

test(testName: string, specFunction: Function): void

其中 specFunction 是一个异步函数,本质上是一个返回逻辑 truefalse 的条件判定函数(也称 predicate 谓词函数)。虽然实测发现,令回调函数返回一个非逻辑值也不会报错,但最好还是按惯例返回逻辑值:

图 6.3 实测回调函数返回值类型:返回一个非逻辑值也不报错,但最好返回逻辑值

【图 6.3 实测回调函数返回值类型:返回一个非逻辑值也不报错,但最好返回逻辑值】

6.1.2 关于 Chai 断言

Postman 中的断言是基于断言库 Chai.jsChai 读作 /ʧaɪ/,同英文单词 chai 的发音,表示“茶叶”)做的二次封装,Chai.js 是一款同时支持 TDD 风格和 BDD 风格的断言库,其名称来自一种印度茶,暗含提供一种友好易用的测试体验的意思。因此刚才的断言逻辑也可以用 Chai.js 重构为:

const chai = require('chai');
pm.test("Status code is 200", function () {
    // pm.response.to.have.status(200);
    chai.expect(pm.response.code).equals(200);
});

实测结果:

图 6.4 在 Postman 中使用 chai 断言重写校验逻辑

【图 6.4 在 Postman 中使用 chai 断言重写校验逻辑】

6.2 检查响应的 body 部分

如果从 Postman 提供的示例脚本中选择 Response body: Contains string,则可以校验响应 body 中是否包含字符串,例如 "skin_color"

pm.test("Body matches string 'skin_color'", function () {
   pm.expect(pm.response.text()).to.include("skin_color");
});

这里的 pm.response.text() 返回字符串形式的响应 body 内容。

如果选择示例代码 Response body:JSON value check,则可以校验请求响应的 JSON 结果,得到如下模板:

pm.test("Your test name", function () {
    var jsonData = pm.response.json();
    pm.expect(jsonData.value).to.eql(100);
});

从第 2 行可见,Postman 的示例脚本还是用的 ES5 语法。这里也可以改为 ES6 的写法。关键是无需从零开始手动构建测试脚本。

此外,回调函数还支持 console.log() 控制台输出,方便调试测试脚本。控制台标签 console 位于主界面的左下角位置。

实测:Luke 的家园 URL 是否正确:

pm.test("Check the homeworld URL", function () {
    const { homeworld } = pm.response.json();
    const expected = 'https://swapi.dev/api/planets/1/';
    pm.expect(homeworld).to.eql(expected);
});

运行结果(书中放到 GitHub 的参考文件是错的,期望值写的是 http,新版响应中为 https):

图 6.5 实测响应 body 为 JSON 数据时,校验 homeworld 字段的值是否正确

【图 6.5 实测响应 body 为 JSON 数据时,校验 homeworld 字段的值是否正确】

6.3 检查请求头 Header

Postman 示例代码:Response header: Content-Type header check

pm.test("Content-Type is present", function () {
    pm.response.to.have.header("Content-Type");
});

这里和最开始校验响应码的写法很像。这也是 BDD 风格的优势:声明式语法,贴近自然语言。

6.4 Postman 常见的断言写法

6.4.1 常见自定义断言对象

PostmanChai.js 的基础上内置了几个常用的自定义断言对象,例如 pm.response.to.have.status 中的 .status,以及检查 Header 时用到的 pm.response.to.have.header 中的 .header

常用的自定义断言对象梳理如下:

自定义对象功能描述断言示例
.statusCode校验响应码的取值pm.response.to.have.statusCode(200);
.statusCodeClass校验响应码所属类别:2 表示以 2 开头的响应码,3 表示以 3 开头的响应码,以此类推pm.response.to.have.statusCodeClass(2);
.statusReason校验响应码描述信息,它是与响应码对应的固定文字描述信息,例如 200 对应 OKpm.response.to.have.statusReason('OK');
.status校验响应码或对应描述信息pm.response.to.have.status(200);
pm.response.to.have.status("Created");
.header校验请求头是否存在,或者请求头的键值对是否正确pm.response.to.have.header("Content-Type");
pm.response.to.have.header("Content-Type", "application/json;");
.withBody校验响应是否包含 bodypm.response.to.be.withBody;
.json检查 body 是否为 JSON 格式pm.response.to.be.json;
.body1. 校验 body 是否存在
2. 校验 body 文本是否完整匹配期望内容
3. 校验 body 是否匹配某正则表达式
4. 校验 body 是否与给定 JSON 匹配
pm.response.to.have.body;
pm.response.to.have.body("JSON text");
pm.response.to.have.body(<regex>);
pm.response.to.have.body({key1:value1,...});
.jsonBody1. 是否为 JSON 格式的响应 body
2. 是否与给定 JSON 匹配 1
pm.response.to.have.jsonBody;
pm.response.to.have.jsonBody({key: value});
.responseTime1. 响应时间精确匹配给定毫秒时间
2. 响应时间不少于给定毫秒时间
3. 响应时间不超过给定毫秒时间
4. 响应时间介于给定时间范围内(单位:ms)
pm.response.to.have.responseTime(150);
pm.response.to.have.responseTime.above(150);
pm.response.to.have.responseTime.below(150);
pm.response.to.have.responseTime.within(100,150);
.responseSize1. 响应内容尺寸精确匹配给定字节大小
2. 响应内容尺寸不少于给定字节大小
3. 响应内容尺寸不超过给定字节大小
4. 响应内容尺寸介于给定字节范围内(单位:字节)
pm.response.to.have.responseSize(50);
pm.response.to.have.responseSize.above(50);
pm.response.to.have.responseSize.below(100);
pm.response.to.have.responseSize.within(50,100);
.jsonSchema校验响应的 JSON 格式的 body 是否与给定 schema 模式匹配pm.response.to.have.jsonSchema(mySchema);

注意:原书 .jsonBody 中的第二个写法是错的,这里为了照顾下一节的实测环节,暂时保留错误写法。正确写法应该是:pm.response.to.have.jsonBody(key, value);

6.4.2 实测情况

(1)实测 .body 对象:

pm.test('The response contains body', () => {
    pm.response.to.have.body;
    pm.response.to.have.body();
});

pm.test('The response body equals expected string', () => {
    const bodyText = pm.response.text();
    pm.response.to.have.body(bodyText);
});

pm.test('The response body matches some RegExp', () => {
    pm.response.to.have.body(/skin_color/i);
});

pm.test('The response body matches expected JSON object', () => {
    const json = pm.response.json();
    pm.response.to.have.body(json);
});

运行结果(匹配文本和 JSON 对象时 必须完全匹配):

图 6.6 实测自定义断言对象 .body 结果截图

【图 6.6 实测自定义断言对象 .body 结果截图】

(2)实测 .jsonBody 对象:

pm.test('The response has a JSON-format body', () => {
    pm.response.to.have.jsonBody;
    pm.response.to.have.jsonBody();
});

pm.test('The response JSON match some key-value pair', () => {
    // Error
    pm.response.to.have.jsonBody({
        'films[2]': 'https://swapi.dev/api/films/3/aaabbbccc'
    });
    // Correct
    pm.response.to.have.jsonBody(
        'films[2]', 'https://swapi.dev/api/films/3/'
    );
});

运行结果:

图 6.7 实测自定义对象 jsonBody 的写法运行结果截图。书中所给的第二个写法是错的,参数不能为一个 JSON 对象

【图 6.7 实测自定义对象 jsonBody 的写法运行结果截图。书中所给的第二个写法是错的,参数不能为一个 JSON 对象】

注意!!!

根据实测结果,校验响应 JSON 中是否包含给定的键值对,不能直接传入一个 JS 对象,而应该按 Postman 提示的方法签名,分别传入 keyvalue 的值作为参数。这里顺便分享一个小技巧,可以很方便的查看 Postman 方法的内置签名:书写脚本时,Postman 会自动提示当前对象的方法签名,遇到存在多个签名的情况,可以使用 Alt + UpAlt + Down 进行翻页,查看隐藏的其他签名。例如 pm.response.to.have.jsonBody() 方法的签名就有四个,如下图所示:

图 6.8.1 pm.response.to.have.jsonBody() 方法存在四种签名

【图 6.8.1 pm.response.to.have.jsonBody() 方法存在四种签名】

// Signature 1
jsonBody(): any
// Signature 2
jsonBody(optionalExpectEqual: any): any
// Signature 3
jsonBody(optionalExpectPath: string): any
// Signature 4
jsonBody(optionalExpectPath: string, optionalValue: any): any

根据实测的上下文,这里显然应该使用第四种签名写法。

(3)实测 .jsonSchema 对象:

校验响应中的 JSON 结构时,旧版 Postman 使用 tv4 模块(tv4 全称 Tiny Validator for JSON Schema version 4);新版中该写法已经废弃,推荐写法为上述列表中的写法,即改用 Ajv 依赖(全称 Another JSON Schema Validator)并作为 pm.response 下的内置对象,实测脚本如下:

// fictional results from pm.response.json();
const json1 = {
    "args": {},
    "films": [],
    "files": {},
    "form": {
        "foo1": "bar1",
        "foo2": "bar2"
    },
    "headers": {},
    "json": null,
    "url": "https://postman-echo.com/post"
};

const schema = {
    type: 'object',
    properties: {
        films: {type: 'array'},
        url: {type: 'string'},
    },
    required: [
        'films', 'url'
    ]
};

pm.test('Response is a valid JSON (via tv4)', function() {
    pm.expect(tv4.validate(json1, schema)).to.be.true;
});

pm.test('Response is a valid JSON (via Ajv)', function() {
    pm.response.to.have.jsonSchema(schema);
});

运行结果:

图 6.8 校验响应 JSON 的 schema 模式时,Postman 新旧两版写法的实测结果对比截图

【图 6.8 校验响应 JSON 的 schema 模式时,Postman 新旧两版写法的实测结果对比截图】

由于本章内容较多,6.4 小节后面的剩余内容放到下篇介绍,敬请期待!


  1. 原书这里的写法有误。根据最新版 Postmanv11.18.2)的实测结果,期望的键值对应该分别作为参数传入 jsonBody() 函数内,具体详见下一节第二个实测案例。 ↩︎


原文地址:https://blog.csdn.net/frgod/article/details/143530006

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!