唐抉的个人博客

自动化接口测试:(一)Postman

字数统计: 2.8k阅读时长: 11 min
2024/06/14

前言

在开发过程中,开发完一个功能后,若是手动一个个取测试新旧功能接口是否正常的操作会比较重复乏味,因此学会对接口自动化测试,一键对新旧接口进行测试可以大大提升功能测试的速度,减少线上出bug的频率。

本文默认读者已掌握Postman基本用法,即已经会使用Postman进行模拟请求的操作。

本文的软件版本如下,不同版本页面的UI和部分功能位置可能会有点不同:

  • window10 64位
  • Postman for Windows 11.2.1

下面将从四点讲述自动化接口测试过程:

  • 接口结果判断:接口是否请求成功
  • 接口批量测试
  • 接口定期测试
  • 接口数据依赖

接口结果判断

接口返回结果主要有两个部分组成:请求返回的code和内容data

因此在使用Postman测试时,主要从两个方面来判断接口结果是否正确:

  • 请求返回的code是否符合预期
  • 请求返回的内容中是否包含预期的内容或关键字

旧版本的Postman功能区在最显眼的地方点击Tests字样,将会切换到接口测试功能,可以在当前面板中编写测试脚本,点击字样,将会切换到预请求脚本的编写页面,可以编写请求运行之前所要执行的JavaScript。

新版本的Postman将预请求脚本和测试脚本合并为一个功能区Scripts,其中在Pre-req面板编写预请求脚本,在Post-res面板里编写测试脚本

注意:在面板中只需要书写结果逻辑判断的代码块,脚本语言只支持JavaScript。在面板右侧的Snippets功能区中,Postman也提供了一些常用的代码模板,利用模板就能处理大部分的情况。

注意:在Postman for Windows 11.2.1中tests、responseBody对象已弃用,因此需要使用断言。如以下代码无法在新版本里生效:

1
2
//检查response body中是否包含某个string
tests["Body matches string"] = responseBody.has("string_you_want_to_search");

具体的代码模板及其注释将附在文末的附录中,有需要的可去文章末尾了解

接口批量测试

批量管理

若想要对接口进行批量测试、统一管理,需要将所有带测试接口全部保存到同一个集合Collections中,这样就可以对接口进行统一管理了。

例如下图中点击save按钮或者按下ctrl+stest接口保存到test的集合中

点击集合名称test打开集合页面,选择Scripts功能区,便可打开集合详情页面

其中Overview为集合概况页;

切换到Authorization可设置接口验证类型;

切换到Scripts可设置接口的测试脚本;

切换到Variables可添加用于编写接口测试脚本的参数变量;

切换到Runs可设置测试任务中接口运行次数、时间间隔、定期运行等状态,并执行测试任务;

向接口传递动参

若想要向接口传入动态变化的参数,可按照下述步骤操作:

  • 对于GET请求,可以在Patams的Value中设置动参引用。如key中输入name, Value中输入{{name}}
  • 对于POST请求,可以将参数输入切换到Body的x-www-form-urlencoded类型,然后在Value中设置动参引用。如key中输入name, Value中输入{{name}}

此处设置好Value后,暂无法使用,需要在预请求脚本中或导入数据集给变量赋值后才能正常使用。

注意:设置好数据集的请求,会将数据集中的数据遍历完成后才视作该接口已完成请求。

预请求给变量赋值

点击Scripts功能区的Pre-request模块,即可编写预请求脚本,页面右方提供了一些常用代码模板可供使用,可以在这里参照代码模板给刚刚设定的动参赋值。

如下图功能为将name变量的值设为’test’并获取name变量的值,

导入数据集批量赋值

首先点击集合名称-Runs功能区-Preformance页面,点击Run Performance Test按钮创建测试任务(任务触发方式默认为手动触发)。

在新弹出的页面中,找到Data File模块,即可在这里上传测试数据文件来实现动参赋值。目前仅支持上传CSVJSON文件.

  • CSV文件数据格式要求如下:

  • JSON文件数据格式要求如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    [
    {
    "name": "zhangsan",
    "number": "123"
    },
    {
    "name": "lisi",
    "number": "456"
    },
    {
    "name": "wangwu",
    "number": "789"
    },
    {
    "name": "zhaoliu",
    "number": "012"
    }
    ]

上传文件后看到点击continue按钮即可成功导入数据集

点击Run即可读取测试集里的数据,进行一次接口测试。

接口定期测试

Postman提供了Schedule runs的功能,支持提交一个按照定时器运行的测试任务。

点击集合名称-Runs功能区-Preformance页面,点击Run Performance Test按钮创建测试任务,切换Functional功能区,选择Schedule runs定时运行,设置好定时器参数便可以点击末尾的Schedule Run按钮定时跑测试任务了。

接口数据依赖

在日常开发中,经常会遇到依赖请求的情况。例如从接口A中查询出记录id,接口B、C、D根据这个id进行一些增删改查的操作。这一过程中,需要处理以下问题:

  • 接口调用顺序
  • 将接口A返回的数据传递给后续的接口B、C、D

接口调用顺序

默认调用顺序

集合中接口的默认调用顺序是按照页面左边的目录顺序从上到下执行的(即test->test1->test2),因此只需要将优先执行的接口放前面即可固定接口的调用顺序.

自定义调用顺序

Postman提供了一个函数setNextRequest()支持跳转到指定接口继续执行;旧版本Postman中该函数的语句为postman.setNextRequest(要跳转的接口名)

注意:

  • 该函数只在运行集合测试时生效,单独接口send时该函数不起作用

  • 运行接口从接口A跳到接口C后,若C后面还有接口DEF,则后面的即可仍会按照默认顺序执行,即DEF仍会被执行

  • 指定的跳转接口必须同属于一个集合中

  • 该函数不管是在何处被调用,都只在当前脚本的最后才会执行

在功能区ScriptsPost-res面板里编写如下代码,可以实现test接口运行成功后跳到test2中继续运行。

1
2
3
4
5
//test接口运行成功后跳到test2中
pm.test("Status code is 200", function () {
pm.response.to.have.status(200);
pm.execution.setNextRequest('localhost/test/api/test2')
});

数据传递

点击侧边栏的Environments,可以创建不同的变量环境,如下图中创建了测试和线上2个环境

通过右边的勾选,可以通过切换不同的环境来设置不同的值

通过设置当前环境的参数集中的参数,可以实现不同接口之间的参数传递。例如在功能区ScriptsPost-res面板里编写如下代码,可以实现test接口运行成功后取其返回name的值作为后续接口的参数res_name

1
2
3
4
5
6
//注意,这个参数res_name的值只会添加在当前选择环境的参数集中
pm.test("Status code is 200", function () {
pm.response.to.have.status(200);
var jsonData = pm.response.json();
pm.environment.set("res_name", jsonData['name']);
});

附录

附录一:旧版本测试模板(直接取值)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
//检查response body中是否包含某个string,注意:"value"为自定义命名,但需唯一。
tests["value"] = responseBody.has("test_value");

//检测JSON中的某个值是否等于预期的值
var data = JSON.parse(responseBody);
tests["value2"] = data.value === 100;
tests["value3"] = data.programs.length === 5;

//转换XML body为JSON对象
var jsonObject = xml2Json(responseBody);
tests["value4"] = responseBody === "response_body_string";

//测试response Headers中的某个元素是否存在(如:Content-Type),不区分大小写
tests["value5"] = postman.getResponseHeader("Content-Type");

//测试response Headers中的某个元素是否存在(如:Content-Type),区分大小写
tests["value6"] = responseHeaders.hasOwnProperty("Content-Type");

//验证Status code的值
tests["value7"] = responseCode.code === 200;

//验证Response time是否小于某个值
tests["value8"] = responseTime < 200;

//name是否包含某个值
tests["value9"] = responseCode.name.has("Created");

//POST请求的状态响应码是否是某个值
tests["value10"] = response

附录二:新旧版本测试模板(通用断言语句):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
//校验响应状态码
pm.test("Status is 200", function () {
pm.response.to.have.status(200);
});

//断言状态码200-202区间
pm.test("Successful GET request", function () {
pm.expect(pm.response.code).to.be.oneOf([200,202]);
});

//校验接口返回状态
pm.test("接口返回状态status ", function () {
var jsonData = pm.response.json();
var status1 =jsonData.status
pm.expect(status1).to.eql(0);
console.log("status1 is :" +status1);
});

//断言响应时间小于200ms
pm.test("Response time is less than 300ms", function () {
pm.expect(pm.response.responseTime).to.be.below(3000);
});

//断言响应中包含某个字符串
pm.test("Body matches string", function () {
pm.expect(pm.response.text()).to.include("FRM");
});

//断言响应中的字段等于某个值
pm.test("message test", function () {
var jsonData = pm.response.json();
pm.expect(jsonData["message"]).to.eql("请求成功");
});

//断言响应中的字段不等于某个值
var jsonData = JSON.parse(responseBody);
tests["message不为failed"] = jsonData["message"] != "failed";

//断言响应中"list"的字段长度
pm.test("data list test", function () {
var jsonData = pm.response.json();
pm.expect(jsonData["data"].length).to.eql(0);
});

//断言响应中"list 0的"的time字段的值
pm.test("data list 0 test", function () {
var jsonData = pm.response.json();
pm.expect(jsonData["data"][0]["time"]).to.eql("2018-11-28 17:27:41");
});

//测试解析json数据
pm.test("Your test name", function () {
var jsonData = pm.response.json();
pm.expect(jsonData.value).to.eql(100);
});

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

//测试是否等于某个字段
pm.test("Body is correct", function () {
pm.response.to.have.body("response_body_string");
});

//请求时间校验
pm.test("Response time is less than 200ms", function () {
pm.expect(pm.response.responseTime).to.be.below(200);
})

//返回值在某个区间
pm.test("Status code name has string", function () {
pm.response.to.have.status("Created");
})

//使用json schema 校验结果
var schema = {
"items": {
"type": "boolean"
}
};
var data1 = [true, false];
var data2 = [true, 123];
pm.test('Schema is valid', function() {
pm.expect(tv4.validate(data1, schema)).to.be.true;
pm.expect(tv4.validate(data2, schema)).to.be.true;
});
CATALOG
  1. 1. 前言
  2. 2. 接口结果判断
  3. 3. 接口批量测试
    1. 3.1. 批量管理
    2. 3.2. 向接口传递动参
      1. 3.2.1. 预请求给变量赋值
      2. 3.2.2. 导入数据集批量赋值
  4. 4. 接口定期测试
  5. 5. 接口数据依赖
    1. 5.1. 接口调用顺序
      1. 5.1.1. 默认调用顺序
      2. 5.1.2. 自定义调用顺序
    2. 5.2. 数据传递
  6. 6. 附录
    1. 6.1. 附录一:旧版本测试模板(直接取值)
    2. 6.2. 附录二:新旧版本测试模板(通用断言语句):