postman接口测试
一、接口测试的简介和分类
接口测试就是测试系统组件接口直接的一种测试。
分类:
测试外部接口:测试被测系统和外部系统之间的接口。(只需要测试正例即可)
测试内部接口:
- 内部接口只提供给内部系统使用。(预算系统,承保系统)(只需测试正例即可)
- 内部接口提供给外部系统使用。(测试必须非常全面,正例,各种异常场景,权限控制)
二、接口测试的流程以及用例的设计
-
拿到接口api文档(没有通过抓包工具获取),熟悉接口业务,接口地址,鉴权方式,入参码。
-
编写接口用例及评审。
思路:
正例:输入正常入参,接口能够成功返回数据。
反例:
-
鉴权反例:
鉴权码为空,鉴权码错误,鉴权码过期,…
-
参数反例:
参数为空,参数类型异常,参数长度异常。
-
错误码覆盖:
根据具体业务而定。
-
其它错误场景:
接口的黑名单,接口调用次数限制,分页场景。
-
-
使用接口测试工具postman执行接口测试。
-
postman+Newman+Jenkins实现持续集成,并且输出测试报告并发送邮件。
三、postman安装说明
postman在2018年之后就不再支持浏览器版本,所以,想要使用它就必须先下载客户端再安装使用,下面就以Windows系统为例进行安装 。
1.下载与安装
postman安装步骤:
- 访问postman官方网站,下载最新版本,访问地址:https://www.getpostman.com/
- 进入到下载页面,根据自己电脑下载对应的版本
双击下载的安装包,进入到安装界面,直到用户登录和注册界面。
- 若个人使用,选择跳过即可,这时会进入到postman主界面,至此postman安装成功(下图)
- 若团队使用,可以进行注册,注册后使用账号可以加入团队工作区
2.界面导航说明
初次使用postman的朋友可能对界面上的一些元素不太熟悉,下面就通过一些图来说明这些元素的含义 。
3.发送请求
如果你是第一次使用postman发送请求,下面这个例子可以作为一个最基本的入门。
- 打开postman,点击+加号打开一个新的请求页。
- 在请求的URL中输入请求地址。
- 点击Send按钮,这时就可以在下部的窗格中看到来自服务器的json响应数据。
请求页签:
- Params:get请求传参。
- Authorization:鉴权。
- Headers:请求头。
- Body:post请求传参。
- form-data:既可以传键值对参数也可以传文件。
- x-www-from-urlencoded:只能传键值对参数。
- raw:json,text,xml,html,JavaScript。
- binary:把文件以二进制的方式传参。
- Pre-request-Script:请求之前的脚本。
- Tests:请求之后的断言。
- Cookies:用于管理cookie信息。
响应页签:
-
Body:接口返回的数据。
- Pretty:以json,html,xml…不同的格式查看返回的数据。
- Paw:以文本的方式查看返回的数据。
- Preview:以网页的方式查看返回的数据。
-
Cookies:响应的cookies信息。
-
Headers:响应头。
-
Test Results:断言的结果。
-
Status:状态码、 ok 状态信息。
-
Time:响应的时间。
-
Size:响应的字节数。
四、Get和Post请求的区别:
- get请求一般是获取数据,post请求一般是提交数据。
- post请求比get请求安全。
- 本质区别是传参的方式不一样:
- get请求再地址栏后面以?的方式传参,多个参数之间用&分隔。
- post请求是再body以表单的方式传参。
五、环境变量以及全局变量
环境变量:环境变量就是全局变量。
全局变量:全局变量是能够在任何接口里面访问的变量。
获取环境变量和全局变量的值通过:{{变量名}}
获取变量值:
全局变量
1 请求参数中的获取 :{{var_name}}
2 代码中获取:var value =pm.globals.get("var_name")
//pm.globals.set("全局变量名",变量值)
var age_tmp=18
pm.globals.set("g_age",age_tmp)
环境变量
1 请求参数中的获取 :{{var_name}}
2 代码中获取:var value =pm.environment.get("var_name")
pm.globals.set('token',token[1]) // 把token保存到全局变量中
pm.environment.set('token',token[1]) // 把token保存到环境变量中
pm.collectionVariables.set('token',token[1]) // 把token保存到集合变量中
六、接口关联
1. 使用json提取器实现接口关联
第一个接口:
//打印语句
console.**log**(responseBody);
//使用json提取器提取access_token值。
//把返回的字符串格式的数据转换成对象的形式。
var result **=** JSON.**parse**(responseBody);
//把access_token设置为全局变量。 (Set a global variable)
pm.globals.**set**("access_token", "result.access_token");
第二个接口:
{{access_token}}
注:
let token = pm.response.json().access_token // 获取token
pm.globals.set('token',token) // 把token保存到全局变量中
2. 使用正则表达式提取器实现接口关联
第一个接口:
//使用正则表达式提取器实现接口关联,match匹配。
var result **=** responseBody.**match**(**new** RegExp('"access_token":"(.*?)"'));
console.**log**(result[1]);
//把access_token设置为全局变量。 (Set a global variable)
pm.globals.**set**("access_token", "result[1]");
第二个接口:
{{access_token}}
注:
let token = responseBody.match('"access_token":"(.*?)"') // 获取token
pm.globals.set('token',token[1]) // 把token保存到全局变量中
3.pm常用对象
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-azcTP7t9-1691203595270)(postman.assets/image-20230805101715447.png)]
七、postman内置动态参数以及自定义的动态参数
内置动态参数:
- {{$timestamp}} 生成当前时间的时间戳。
- {{$randomlnt}} 生成0-1000之间的随机数。
- {{$guid}} 生成速记GUID字符串。
自定义动态参数:
//手动获取时间戳
var times = Data.now();
//设置为全局变量
pm.globals.set("times",times);
//使用时使用:
{{times}}
八、断言
如果没有断言,我们只能做接口的功能测试,但有了断言后,就为我们做自动化提供了条件,并且在postman中的断言是非常方便和强大的 。
我们先来了解下postman断言的一些特点 ,具体如下
- 断言编写位置:Tests标签
- 断言所用语言:JavaScript
- 断言执行顺序:在响应体数据返回后执行 。
- 断言执行结果查看:Test Results
在上面我们介绍到,编写的断言代码是JavaScript,那如果不会写怎么办 ? 不用担心,因为postman已经给我们内置了一些常用的断言 。用的时候,只需从右侧点击其中一个断言,就会在文本框中自动生成对应断言代码块 。
接下来就让我们了解一些常用断言,还是按响应的组成来划分,分别是状态行,响应头,响应体。
状态行中又包括状态码,状态消息 。在postman也可以对这两个进行断言
状态行中的断言:
- 断言状态码:Status code: code is 200
pm.test("Status code is 200", function () {
pm.response.to.have.status(200); //这里填写的200是预期结果,实际结果是请求返回结果
});
- 断言状态消息:Status code:code name has string
pm.test("Status code name has string", function () {
pm.response.to.have.status("OK"); //断言响应状态消息包含OK
});
响应头中的断言:
- 断言响应头中包含:Response headers:Content-Type header check
pm.test("Content-Type is present", function () {
pm.response.to.have.header("Content-Type"); //断言响应头存在"Content-Type"
});
断言响应体(重点)
- 断言响应体中包含XXX字符串:Response body:Contains string
pm.test("Body matches string", function () {
pm.expect(pm.response.text()).to.include("string_you_want_to_search");
});
//注解
pm.expect(pm.response.text()).to.include("string") 获取响应文本中包含string
- 断言响应体等于XXX字符串:Response body : is equal to a string
pm.test("Body is correct", function () {
pm.response.to.have.body("response_body_string");
});
//注解
pm.response.to.have.body("response_body_string"); 获取响应体等于response_body_string
- 断言响应体(json)中某个键名对应的值:Response body : JSON value check
pm.test("Your test name", function () {
var jsonData = pm.response.json();
pm.expect(jsonData.value).to.eql(100);
});
//注解
var jsonData = pm.response.json() 获取响应体,以json显示,赋值给jsonData .注意:该响应体必须返会是的json,否则会报错
pm.expect(jsonData.value).to.eql(100) 获取jsonData中键名为value的值,然后和100进行比较
响应时间(一般用于性能测试)
- 断言响应时间:Response time is less than 200ms
pm.test("Response time is less than 200ms", function () {
pm.expect(pm.response.responseTime).to.be.below(200); //断言响应时间<200ms
});
在断言中获取自定义动态参数(全局变量)的方式:
- pm.globals.get(“times”)
- globals[“times”]
- globals.times
示例:
- 请求方法:POST
- 请求URL: https://cx.shouji.360.cn/phonearea.php?number=13355104523
//断言状态码:Status code: code is 200
pm.**test**("Status code is 200", **function** () {
pm.response.to.have.status(200);
});
//断言状态消息:**Status code:code name has string**
pm.**test**("Status code name has string", **function** () {
pm.response.to.have.status("OK");
});
// 断言响应头中包含:Response headers:Content-Type header check
pm.**test**("Content-Type is present", **function** () {
pm.response.to.have.header("Content-Type");
});
// 断言响应体中包含XXX字符串:Response body:Contains string
pm.**test**("Body matches string", **function** () {
pm.expect(pm.response.text()).to.include("sp");
});
//断言响应体等于XXX字符串:Response body : is equal to a string
pm.**test**("Body is correct", **function** () {
pm.response.to.have.body({
"code": 0,
"data": {
"province": "山东",
"city": "济宁",
"sp": "电信"
}
});
});
//断言响应体(json)中某个键名对应的值:Response body : JSON value check
pm.**test**("Your test name", **function** () {
var jsonData **=** pm.response.json();
pm.expect(jsonData.data.city).to.eql("济宁");
});
//断言响应时间:Response time is less than 200ms
pm.**test**("Response time is less than 200ms", **function** () {
pm.expect(pm.response.responseTime).to.be.below(200);
});
九、批量执行测试用例
十、参数化
postman 读取外部文件
参数化中 一般用2种文件测试去读取文件信息
csv
优点:组织数据形式非常简单,使用于大量数据的场合
缺点:不支持bool 类型的数据 (被csv包含的数据在被postman 读取的时候会自动添加“”)
不支持复杂的数据类型 嵌套字典 列表
json
优点:支持bool 类型的数据
支持复杂的数据类型
缺点:对于相同的数据量json 数据的文件远大于csv 文件的
读取文件的语法
使用的数据不同,是不是获取文件数据的方法页不同
第一种:请求参数(请求头,请求行,请求体)使用文件中的数据
使用{{}}去包裹csv 文件字段名或者json中的key
r如{{username}}
第二种:在代码去使用数据(断言,前置脚本)
需要借助postman 提供的关键字data . csv文件中的字段名
或者data.json 文件中key
data.username
data.password
案列:
需求:
批量查询手机号归属地 所属运营商,校验运营商数据的正确性
接口:https://cx.shouji.360.cn/phonearea.php?number=13355104523
测试数据;
手机号:13012345678 运营商:联通
手机号:13812345678 运营商:移动
手机号:18912345678 运营商:电信
断言运营商:
编写测试数据:
导入外部文件:
修改代码 参数化:
运行数据:
十一、测试必须带请求头的接口
常见的请求头
Host 请求的主机地址
Connection 连接方式
Referer 来源
Accept 客户端接收到的数据格式
X-Requested-With 异步请求
User-Agent 客户端的用户类型
Cookie Cookie信息
Content-Type: 请求内容的格式
十二、postman接口Mock Server服务器
mock 模拟
后端的接口还没有开发完成,前端的业务需要调整后端的接口
十三、postman的Cookie鉴权
cookie是一小段文本,格式key=value。
cookie鉴权的原理:
- 当客户端第一次访问服务器的时候,那么服务器就会生成Cookie信息,并且在响应头的set-cookie里面把生成的cookie信息发送给客户端。
- 当客户端第2-N次访问服务器的时候,那么客户端就会在请求头的cookie带上cookie信息,从而实现鉴权。
cookie的分类:
- 会话cookie:保存在内存,当浏览器关闭之后就会自动化清除cookie。
- 持久cookie:保存在硬盘,浏览器关闭后不会清楚,只有当失效时间到了才会自动清除。