赞
踩
下载:
测试外部接口:测试被测系统和外部系统之间的接口。(只需要测试正例即可)
测试内部接口:
1.内部接口只提供给内部系统使用。(只需要测试正例即可)
2.内部接口提供给外部系统使用。(测试必须非常全面,正例,各种异常场景,权限控制)
1.向开发要接口api文档(没有的话通过抓包工具获取):
熟悉接口业务,接口地址,入参,出参,鉴权码
2.编写接口用例以及评审
思路:
正例:输入正常入参,接口能够成功返回数据
反例:
项目名称 | 程序版本 | ||||||||
测试环境 | |||||||||
用例编号 | 测试接口 | 用例标题 | 请求方式 | 预置条件 | 操作步骤 | 输入数据 | 预期结果 | 优先级 | 数据库结果 |
最好要注册,要不然会影响一些功能
步骤:
1.创建项目
添加请求
右键--添加请求
请求url:
https://api.thecatapi.com/v1/votes
header
Content-Type:application/json
x-api-key:DEMO-API-KEY
请求页签
Params:get请求传参
Authorization:鉴权
headers:请求头
Body:post请求传参
- form-data:既可以传键值对参数也可以传文件
- x-www-form-urlencoded:只能够传键值对参数
- raw:可以传Text、JavaScript、JSON、HTML、XML
- binary:把文件以二进制的方式传参
Pre-request Script:请求之前的脚本
Tests:接口请求之后的脚本、断言
Coolies:用于管理cookies信息
响应页签:
Body:接口返回的数据
Pretty:以JSON XML HTML Text不同格式查看返回的数据
Row:以文本的方式查看返回的数据
Preview:以网页的方式查看返回的数据
Cookies:响应的Cookies信息
Headers:响应头
Test Results:断言的结果
200 状态码
OK 状态信息
441ms 响应的时间
743B 响应的字节数
请求地址:
https://api.thecatapi.com/v1/votes
HEADERS
Content-Type:application/json
x-api-key:DEMO-API-KEY
BODY raw
- {
- "image_id":"39i",
- "sub_id": "my-user-1234",
- "value":4
- }
面试题:
get请求和post请求的区别:
1.get请求一般是获取数据,post请求一般是提交数据。
2.post请求比get请求安全。
3.本质区别是传参的方式不一样:
- get请求在地址栏后面以?的方式传参,多个参数之间用&分隔。
- post请求是在body以表单的方式传参。
以上的问题:
多种环境:开发环境,测试环境,生产环境(两个接口的域名是一样的)
接口关联:需要手动关联(第一个接口返回的token值手动填到第二个接口的参数)
参数需要手动修改(name参数不能与已存在的标签名重复,每次修改需手动修改)
开发环境,测试环境(变量名保持一致,都为ip)
用双大括号加变量名的方式来取得环境变量的值
send前,选择哪个环境
环境变量:环境变量就是全局变量
全局变量:全局变量是能够在任何接口里面访问的变量
获取环境变量和全局变量的方法:{{变量名}}
使用json提取器实现接口关联(只能针对Josn数据)
第一个接口:
- console.log(responseBody); //打印
- //使用json提取器提取id值
- //把返回的字符串格式的数据转换成对象的形式。
- var result = JSON.parse(responseBody);
- //把id设置为全局变量
- //pm.globals.set("id", "result.id");
- pm.globals.set("id", "result[1].id");
第二个接口
{{id}}
我用的接口没有 token,可以看下面的部分(十四 Postman的Cookie鉴权和Token鉴权)
使用正则表达式的方式实现接口关联
正则表达式
- 开始标志位双引号"+正则表达式提取内容+结束标志位双引号"
- 需要传递获取的值用(.*?)代替
- 如果提取的内容含有双引号,那么标注位的双引号变为单引号
第一个接口
- console.log(responseBody); //打印
- //判断当返回结果中包含有id时才通过正则表达式去取值
- if (responseBody.search("image_id")!=-1){
- //使用正则表达式提取器实现接口关联,match匹配。
- var result1 = responseBody.match(new RegExp('"image_id":"(.*?)"'));
- console.log(result1); //控制端输出结果
- var result2 = responseBody.match(new RegExp('"image_id":"(.*?)i'));
- console.log(result2); //控制端输出结果
- var result3 = responseBody.match(new RegExp('"image_id":"(.*?)9i'));
- console.log(result3); //控制端输出结果
- //设置为全局变量
- pm.globals.set("mage_id",result1[1]);}
- //业务断言
- pm.test("检查响应中包含的值", function () {
- pm.expect(pm.response.text()).to.include(31102);
- });
第二个接口:
{{mage_id}}
postman内置动态参数:
- {{$timestamp}} //生成当前时间的时间戳
- {{$randomint}} //生成0-1000之间的随机数
- {{$guid}} //生成速记GUID字符串
1.自定义时间戳参数
调用变量用{{times}}
- //自定义动态参数时间戳
- var times = Date.now();
- console.log(times)
- //设置为全局变量
- pm.globals.set("times", times);
2.随机整数
- //随机数
- const randomInt = (min, max) => Math.floor(Math.random() * (max - min + 1)) +min;
- //打印
- console.log(randomMobile(100000000,999999999));
3.随机手机号
- //随机数
- const randomInt = (min, max) => Math.floor(Math.random() * (max - min + 1)) +min;
- //随机手机号
- var randomMobile = `18${randomInt(100000000,999999999)}`;
- //打印
- console.log(randomMobile);
4.等待时间
有些接口有调用时 2限制,5秒之内只能调用1次。
- const sleep = (milliseconds) => {
- const start = Date.now();
- while (Date.now() <= start + milliseconds) {}
- };
- //等待2秒
- sleep(2000)
也就是一个增删改查的闭环
常规的六种断言:
Status code:Code is 200 检查返回的状态码是否为200
Resoonse body:Contains String 检查响应中包含指定字符串
Response body:JSON value check 检查响应中其中json的值
Response body:Is equal to a string 检查响应等于一个字符串
Response headers:Content-Type header check 检查是否包含响应头Content-Type
Response time is less than 200ms 检查请求耗时小于200ms
点击右侧可以直接插入断言
- //断言
- //状态断言
- pm.test("检查返回状态码为200", function () {
- pm.response.to.have.status(200);
- });
- //业务断言
- pm.test("检查响应中包括id", function () {
- pm.expect(pm.response.text()).to.include("id");
- });
- //检查响应头中包含有Content-Type响应头
- pm.test("Content-Type is present", function () {
- pm.response.to.have.header("Content-Type");
- });
- //检查响应时间少于500ms
- pm.test("Response time is less than 200ms", function () {
- pm.expect(pm.response.responseTime).to.be.below(500);
- });
- //业务断言
- pm.test("检查响应中id值", function () {
- var jsonData = pm.response.json();
- pm.expect(jsonData.id).to.eql(31102);
- });
可以把状态断言放到全局断言里
点击run后,进行设置
run运行
运行结果:
注意:
在批量运行测试用例时,如果接口中含有需要上传文件的接口,那么需要把文件存放在工作目录下,且允许访问外部工作目录
用第一个接口来做数据驱动,也就是说既有正例,又有反例
在任意位置新建一个CSV文件
当数据文件写好之后,第一个要改的地方,参数取数据文件里面的值也是用双大括号来取
第二个要改的地方,断言的时候写死的,要改成从数据文件里面取:
或者用apidata01["assert_value"]
- console.log(responseBody); //打印
- //使用json提取器提取id值
- //把返回的字符串格式的数据转换成对象的形式。
- var result = JSON.parse(responseBody);
- //把id设置为全局变量
- //pm.globals.set("id", "result.id");
- pm.globals.set("id", "result[1].id");
- //断言
- //状态断言
- pm.test("检查返回状态码为200", function () {
- pm.response.to.have.status(200);
- });
- //业务断言
- pm.test("检查响应中包括id", function () {
- //pm.expect(pm.response.text()).to.include("id"); 修改前
- pm.expect(pm.response.text()).to.include(apidata01.assert_value); //修改后
- });
- //检查响应头中包含有Content-Type响应头
- pm.test("Content-Type is present", function () {
- pm.response.to.have.header("Content-Type");
- });
- //检查响应时间少于500ms
- pm.test("Response time is less than 200ms", function () {
- pm.expect(pm.response.responseTime).to.be.below(500);
- });
判断当返回结果中包含有id时才通过正则表达式去取值
- //判断当返回结果中包含有id时才通过正则表达式去取值
- if (responseBody.search("id")!=-1){
- //使用正则表达式提取器实现接口关联,match匹配。
- var result = responseBody.match(new RegExp('"id":"(.*?)"'));
- console.log(result[1]); //控制端输出结果
- //设置为全局变量
- pm.globals.set("id",result[1]);}
- //业务断言
- pm.test("检查响应中包括id", function () {
- //pm.expect(pm.response.text()).to.include("id"); 修改前
- pm.expect(pm.response.text()).to.include(apidata01.vote_id); //修改后
- });
哪个接口有用到csv文件,哪个接口就☑️
然后运行
新建一个文件data.json
(mac:终端cd进入要创建文件的路径下,使用touch apidata.json指令即可)
- [
- {"vote_id":"31102","assert_value":"31102"},
- {"vote_id":"31104","assert_value":"31104"}
- ]
其他操作都一样
常见的请求头:
Host 请求的主机地址
Connection 连接方式
Accept 客户端接收到的数据格式
X-Requested-With 异步请求
User-Agent 客服端的用户类型
Referer 来源
Cookie Cookie信息
Content-Type 请求内容的格式
测试接口
https://www.baidu.com/s?wd=接口测试
如果没有加请求头的话,会发现响应显示有问题(至于哪个请求头是必填的,一般需要自己一个个的试)
mock模拟
后端的接口还没有开发完成,前端的业务需要调用后端的接口。
下图中 2 部分的请求方式(GET)和URL中的 (test)都可以根据实际的需要进行修改
1. 自动生成一个环境变量:
2. 自动生成一个项目和请求
假设前端想要返回的数据如下(前端需要什么数据就填写什么数据)
{“error_code”:0,“msg”:“返回成功”,data:[]}
那就在default里面直接替代掉success,保存再去发送请求的时候就得到了想要的数据
再次发送效果:
在浏览器里访问测试下:
什么是cookie?
cookie是一小段文本,格式key=value。
cookie鉴权的原理:
1.当客户端第一次访问服务器的时候,那么服务器就会生成Cookie信息,并且在响应头的set-cookie里面把生成的cookie信息发送给客户端。
2.当客户端第N次(N>1)访问服务器的时候,那么客户端就会在请求头的cookie带上cookie信息,从而实现鉴权。
cookie的分类:
会话cookie:保存在内存,当浏览器关闭之后就会自动化清除cookie。
持久cookie:保存在硬盘,浏览器关闭后不会清除,只有当失效时间到了才会自动清除。
F5刷新页面,浏览器按F12, Application->Cookies查看cookie:
1.访问phpwind论坛首页接口
http://47.107.116.139/phpwind/
查看cookies
2.正则表达式提取token值
input type="hidden" name="csrf_token" value="13311087a61defe0"
正则表达式提取token值,在第二个接口请求参数里面用,实现token关联鉴权。
- var result = responseBody.match(new RegExp('name="csrf_token" value="(.*?)"'));
-
- console.log(result);
- //将 csrf_token设置为全局变量
- pm.globals.set("csrf_token", result[1]);
http://47.107.116.139/phpwind/index.php?m=u&c=login&a=dorun
接口一发送成功后,自动生成3个cookie,接口二带上这3个cookie请求才会成功(接口二的 3 个 cookie默认自动加上)
登录的抓包Header信息:
参数设置:
抓包的 Body部分
结果有success就是成功的!
对称式加密:DES,AES,Base64加密算法
非对称加密:双钥(公钥,私钥,公钥加密私钥解密,私钥加密公钥解密)加密,RSA加密算法
不考虑加密:MD5,SHA1,SHA3
加密
解密
AES和上面的一样
对admin进行公钥加密
用私钥进行解密
一般MD5加密,使用的是 “32 位大写 ”
解密
市面上所有的加密中,MD5的加密使用是最广泛的
接口说明:
自定义的基于 flask的加密接口
postman中api设置:
对 username和password进行MD5加密 (在Pre-req中设置)
- //poatman的MD5加密的方法
- //打印 32 位小写
- //var username = CryptoJS.MD5("admin").toString();
- //打印 32 位大写
- var username = CryptoJS.MD5("admin").toString().toUpperCase();
- var password = CryptoJS.MD5("123").toString().toUpperCase();
- console.log(username)
- console.log(password)
- //设置全局变量
- pm.globals.get("username",username);
- pm.globals.get("password",password);
然后,设置变量
实际运行接口会不成功,因为是本地接口,这个不重要,主要了解postman的MD5如何加密的即可!
newman和newman-reporter-html下载安装
postman是专为接口测试而生,Newman是专为postman而生。newman可以让我们的postman的脚本通过非GUI(命令行)的方式。这样就可以和jenkins集成。
运行命令:newman run
常用参数:
-e 引用环境变量(开发环境/测试环境/生产环境)
-g 引用全局变量
-d 引用数据文件
-n 指定测试用例迭代的次数
-r cli,html,json,junit --reporter-html-export 指定生成HTML的报告
选择一个位置,新建一个名为postman的文件夹
然后
1.1 导出测试用例
导出名称改为test_case.json
1.2 导出生产环境
导出名称改为environment.json
1.3 导出全局变量
导出名称改为globals.json
1.4 数据文件也存放到postman文件夹中
总的导出文件如下:
1. 5 通过newman运行用例
进入 postman文件夹的路径下
运行
newman run test_case.json -e environment.json -g globals.json -d apidata01.csv -r cli,html,json,junit --reporter-html-export report.html
在 postman文件夹下,可以看到生成的html报告
用newman-reporter-htmlextra可以导出更漂亮的报告
newman run test_case.json -e environment.json -g globals.json -d apidata01.csv -r cli,htmlextra,json,junit --reporter-HTML-export report.html
或者不需要 json junit也可以
newman run test_case.json -e environment.json -g globals.json -d apidata01.csv -r htmlextra,cli
不知道是浏览器还是 Mac电脑的问题,我查看的报告也不是很漂亮。。。
我用的版本是Jenkins 2.440.2 (jenkins页面右下角可查看)
2.1 安装HTML Publisher插件/Groovy插件/Startup Trigger插件
安装后可以在“Installed plugins”已安装列表查看
2.2 安装 newman
和 newman-reporter-html
2.2.1 安装 nodejs plugin
2.2.2 全局管理工具配置
安装 newman和newman-reporter-html
安装成功以后,Global npm packages to install部分的安装内容就可以不填了
查看是否安装成功:
创建Jenkins自由风格项目
步骤 1
步骤 2
构建结果
newman-reporter-html 安装及验证
——————————————————————————————————
3.1 进入 jenkins,新建项目
3.2 回到 jenkins首页,选择上一步创建的项目,进行配置Configure
配置上面导出的文件所在的空间(即 postman文件夹路径)
3.3 构建Execute NodeJS script
3.4 执行windows的批处理命令
构建 Execute windows batch command
macOS构建 Execute shell
newman run test_case.json -e environment.json -g globals.json -d apidata01.csv -r cli,html,json,junit --reporter-html-export report.html
masOS
- cd /Users/mac/Documents/study23/postman
- newman run test_case.json -e environment.json -g globals.json -d apidata01.csv -r cli,html,json,junit --reporter-html-export report.html
3.5 执行系统的Groovy脚本(目的:报告显示的样式可正常显示)
构建 Execute system Groovy script
System.setProperty("hudson.model.DirectoryBrowserSupport.CSP","")
mac
3.6 生成的HTML报告集成到jenkins
构建后操作 Publish HTML reports
3.7 项目运行
保存完成后,回到jenkins首页,posyman项目右键build now:
Jenkins内也能查看报告
点击批准即可
报告的路径设置问题或权限问题
Postman可以用来创建、发送、调试和记录HTTP请求,并且可以自动化测试流程和代码生成,并支持多种HTTP请求方法(GET、POST、PUT、DELETE等)和数据格式(JSON、XML、HTML等)。
因此,我们可以将Postman接口测试定义为通过使用Postman工具来验证API是否能够正确地响应预期的请求并返回正确的响应数据。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。