一、接口测试和Mock学习路线-第一阶段:
- 掌握接口测试的知识体系与学习路线
- 掌握面试常见知识点之 HTTP 协议
- 掌握常用接口测试工具 Postman
- 掌握常用抓包工具 Charles 与 Fiddler
- 结合知名产品实现 mock 测试与接口测试实战练习
1.接口协议:
需要先了解 OSI 七层模型、TCP/IP 四层模型、五层体系结构这三种不同的网络模型
OSI
参考模型是一个在制定协调进程间通信标准时所使用的概念性框架,它并不是一个标准。TCP/IP
四层模型是网际网络的基础通信架构。常视为是简化的七层 OSI 模型。- 五层协议是
OSI
和TCP/IP
的综合,实际应用还是TCP/IP
的四层结构。 TCP/IP
协议栈是对应TCP/IP
四层模型所使用的具体的网络协议。
1.1.TCP 协议
TCP 协议是在传输层中,一种面向连接的、可靠的、基于字节流的传输层通信协议。TCP 协议的工作方式为在建立连接的时候需要进行“三次握手”,终止连接时需要进行“四次挥手”。(三次握手四次挥手需要掌握)
适用场景
TCP 协议的面向连接、错误重传、拥塞控制等特性,适用于可靠性高的场景,比如涉及用户信息的数据传输。
1.2.UDP 协议
UDP 协议一旦把应用程序发给网络层的数据发送出去,就不保留数据备份。它仅在 IP 数据包的头部加入复用和数据校验字段。所以 UDP 常常被认为是不可靠的数据包协议。
适用场景
UDP 协议的不需要提前建立连接、实现简单的特性,非常适用于实时性高的场景,比如流媒体、在线游戏等。
1.3.RPC 协议
RPC 的英文为 Remote Procedure Call ,它很好的诠释了 RPC 协议的概念,即为以本地代码调用的方式实现远程执行,RPC 主要用于公司内部的服务调用。RPC 接口的优点在于传输效率更高、性能损耗更低、自带负载均衡策略、更好的服务治理能力。
常见的 RPC 协议
目前在行业内常用的 RPC 协议主要如下:
- Dubbo:Java 上的高性能 RPC 协议,Apache 开源项目,由阿里捐赠 底层应用层协议支持 Dubbo 缺省 TCP 协议、HTTP、Hessian、Thrift、gRPC 等。
- gRPC:高性能通用 RPC 框架,基于 Protocol Buffers。
- PB(Protocol Buffers):是一个语言中立、平台中立的数据序列化框架。Google 开源项目。
- Thrift:与 gRPC 类似的多语言 RPC 框架,Apache 开源项目。
- JSON-RPC:A light weight remote procedure call protocol. It is designed to be simple。
1.4.HTTP 协议
HTTP 协议是接口测试中最常见的协议,是用于分布式、协作式和超媒体信息系统的应用层协议。HTTP 是万维网的数据通信的基础。客户端向服务端发送 HTTP 请求,服务端则会在响应中返回所请求的数据。在测试过程中,常常需要校验请求和响应结果,所以了解 HTTP 协议,对于接口测试来说,是重中之重。
- 请求
- 请求行:method url protocol
- 请求方法:GET、POST、PUT、DELETE、HEAD
- 请求头: Host Cookie User-Agent
- 请求参数 query
- 请求体:JSON XML FORM
- 响应:
- 响应状态行
- 响应头
- 响应体
1.4.1.URI 和 URL
- URI,统一资源标识符,用来唯一的标识一个资源。
- URL,统一资源定位符,它是一种具体的 URI
- URL 结构:
https://www.baidu.com/s?wd=霍格沃兹&rsv_spt=1
- 协议:
http
- 域名:
www.baidu.com
- 端口:跟在域名后面,域名和端口之间使用“:”作为分隔符,非必须,如果省略端口部分将采用默认端口
- 路径:
/s
- 请求参数:
wd=霍格沃兹&rsv_spt=**1
- 协议:
> GET /uploads/user/avatar/31438/8216a3.jpg HTTP/1.1
> Host: ceshiren.com
> Accept-Encoding: deflate, gzip
> Connection: keep-alive
> Pragma: no-cache
> Cache-Control: no-cache
> User-Agent: Mozilla/5.0
(Macintosh; Intel Mac OS X 10_15_0)
AppleWebKit/537.36
(KHTML, like Gecko)
Chrome/80.0.3987.116 Safari/537.36
> Accept: image/webp,image/apng,image/*,*/*;q=0.8
> Referer: https://ceshiren.com/
> Accept-Language: en,zh-CN;q=0.9,zh;q=0.8
> Cookie: user_id=xx;
_homeland_session=xx;
>
< HTTP/1.1 200 OK
< Server: nginx/1.10.2
< Date: Thu, 12 Mar 2020 09:13:44 GMT
< Content-Type: image/png
< Content-Length: 11390
< Connection: keep-alive
HTTP 响应状态码
1xx
临时响应,表示通知信息,请求收到了或正在进行处理2xx
表示成功,接受或知道了200
成功
3xx
表示重定向,要完成请求还必须才去进一步的行动301
永久移动302
临时移动
4xx
表示客户端请求错误403
未授权404
未找到
5xx
表示服务端错误500
服务器内部错误503
服务不可用
RESTful 架构
使用 URL 去定位资源,使用 HTTP 动词描述操作。
HTTP 请求方法在 RESTful API 中的典型应用:
方法 | 意义 |
---|---|
GET | 获取资源 |
POST | 新增或者更新 |
PUT | 更新资源 |
DELETE | 删除资源 |
注意: 不同公司在使用 RESTful 架构风格的时候存在部分差别。
get 与 post 区别
在日常的工作当中,HTTP 请求中使用最多的就是 GET
和 POST
这两种请求方式.那么掌握这两种请求方式的原理,以及两种请求方式的异同,也是之后做接口测试一个重要基础。
- 请求方法不同。
- POST 可以附加 body,可以支持
Form
、JSON
、XML
、Binary
等各种数据格式。 - 从行业通用规范的角度来说,如果对数据库不会产生数据变化的,比如查询操作,建议使用 GET 请求,数据的写入与状态建议用 POST 请求。
接口测试用例设计
接口测试在需求分析完成之后,即可设计对应的接口测试用例,然后根据用例进行接口测试。接口测试用例的设计也需要用到黑盒测试用例设计方法,和测试流程的功能测试用例设计的方法类似,设计过程中还需要增加与接口特性相关的测试用例
接口测试的质量目标
- 功能
- 性能
- 安全
- 兼容
- 健壮性
- 高可用性(中间件)
协议分析方法
- 网络监听:
- TcpDump
- WireShark
- 代理 Proxy
- 推荐工具:手工测试 Charles [全平台]、安全测试 BurpSuite [全平台 Java]
- 自动化测试:mitmproxy
- 其他代理: Fiddler [仅 Windows]、AnyProxy [全平台]
二、接口测试用例的设计方法
正式设计接口测试用例之前,需要梳理一下接口测试的思路:
1.基本功能流程测试
在基本功能流程测试方面,首先需要先执行冒烟测试,把最基本的功能流程走通。冒烟测试决定提测是否成功,如果通过冒烟测试,才会进入到详细的测试阶段。如果冒烟测试不通过,需要打回给开发,开发修改之后重新提测。 冒烟测试通过之后,进行正常流程覆盖测试,粒度会比冒烟测试更细一些,覆盖一些分支业务逻辑。
2.基于输入域的测试
因为发出接口请求需要携带请求参数,所以肯定会涉及到关于请求参数的各种用例的设计。关于请求参数的用例设计可以考虑下面这些方面。
- 边界值测试
对于有范围要求的参数,需要综合等价类和边界值的方法设计测试用例。边界值选择上点和离点即可,要覆盖到有效等价类和无效等价类。
- 特殊字符校验
对于很多请求参数会要求不能包含特殊字符,对于有这类要求的字段,需要单独设计包含特殊字符的测试用例来做验证。
- 参数类型校验
有一些参数还会对于传参值的类型有要求,比如只能包含英文数字,或者只能包含整数类型等。对于这种对类型有要求的字段,也要单独设计测试用例,设计一些反向用例来做验证。
- 必选参数校验
在接口中有必填的参数,也有选填的参数。对于每一个必填参数,都要设计一条不传的用例来验证必填性。
- 组合参数校验
对于有选填参数的接口来说,需要对于各种参数的不同组合场景进行验证。比如只传必填参数,或者必填参数和不同数量的选填参数做组合的场景,可以使用判定表的方法进行设计。
- 排重逻辑
如果有的字段要求不能重复,那么需要对它进行排重逻辑的覆盖,看看重复请求相同的参数,服务端的处理逻辑是不是正确。
- 接口幂等性
幂等是指任意多次执行所产生的影响均与一次执行的影响相同。保证接口的幂等性是非常重要的,尤其是在涉及资金的系统,比如如银行、电商系统等。 例如用户重复提交请求,或者网络重发,系统重试等场景,都需要设计测试用例来保证接口的幂等性。接口的幂等测试,需要多次发送同一参数的请求,查看服务端响应是否只有一次是成功的。
3.线程安全测试
线程安全测试包含了并发测试、分布式测试。
分布式更多的一个概念,是为了解决单个物理服务器容量和性能瓶颈问题而采用的优化手段。
分布式的实现有两种形式:
- 水平扩展:当一台机器扛不住流量时,就通过添加机器的方式,将流量平分到所有服务器上,所有机器都可以提供相当的服务。
- 垂直拆分:前端有多种查询需求时,一台机器扛不住,可以将不同的需求分发到不同的机器上。
相对于分布式来讲,高并发在解决的问题上会集中一些,它的重点是测试同时有多少量,比如在线直播服务同时有上万人观看。
高并发可以通过分布式技术去解决,将并发流量分到不同的物理服务器上。但除此之外,还可以有很多其他优化手段,比如使用缓存系统,还可以使用多线程技术将一台服务器的服务能力最大化。
对于并发场景,需要测试多个相同参数的请求,只有一条请求成功,其他请求失败。
对于分布式测试,则需要测试在分布式环境中并发相同参数的请求,只有一条请求成功,其他请求失败。
4.故障注入
故障注入测试需要测试人员故意制造故障的场景,来保证系统的健壮性。
如果产品中用到了 Redis,就需要对于 Redis 做一些故障降级测试。Redis 一般会放在数据库前面,用来做高速缓存。
Redis 故障注入需要开发配合清空 Redis 数据,发请求,击穿 Redis,从 DB 中获取正常的数据,并能回写到 Redis 中。然后开发配合启动 Redis 数据恢复功能,测试可以从 Redis 中获取正确的数据。还需要开发配合制造 Redis 崩溃场景,发请求,测试是否降级从 DB 中获取到正常的数据。
除了 Redis 之外,还需要进行服务故障转移测试。比如数据库故障测试与接口故障测试。
数据库故障测试,开发配合制造数据库数据丢失场景,启动数据恢复策略,测试规定时间段内数据是否可以恢复;开发配合制造数据库崩溃场景,测试数据库多活策略是否启动,保证功能不受影响。
接口故障测试,开发配合接口服务重启,测试集群负载是否自动重启实例,所有请求无异常;开发配合制造集群崩溃场景,测试是否返回对应的错误信息,内部服务是否有重试机制。
5.接口测试用例要素
- 模块
- 测试标题
- 优先级
- 前置条件
- 请求方法
- 请求参数
- 预期结果
- 实际结果
三.postman基础使用
1.介绍:
Postman是一款流行的API测试工具和开发环境,旨在简化API开发过程、测试和文档编制。它提供了一套功能强大的工具,帮助开发人员更轻松地构建、测试和调试Web服务。
- Postman 可以快速构建请求、还可以保存以后再使用
- Postman 还提供响应结果的比较功能,可以用来写测试用例。使用 Postman 查看测试结果也非常的方便,可以自定义一些预期的结果,根据 Postman 给返回的
pass
或者fail
就可以判断出测试是不是通过。
- Postman 还可以把测试用例放在测试集中批量运行,方便各种业务场景的测试和回归。
- 一般来说测试接口肯定是要会有很多套环境的,比如说生产环境、测试环境,正式环境等等。在 Postman 中可以通过设置不同的环境变量,很方便的使用同一套测试用例,只是切换到不同的测试环境就可以。
2.应用:
API 测试:Postman 可以用来快速、简便地测试 API 接口,通过发送HTTP请求并查看响应数据来验证接口的功能是否正常。
自动化测试:Postman 提供了强大的测试脚本功能,可以编写测试脚本来自动化执行接口测试,减少人工测试工作量。
性能测试:Postman 可以用来执行性能测试,通过模拟大量用户同时访问接口来评估接口的性能表现。
监控和断言:Postman 可以设置监控脚本,定期检查接口的可用性和性能,并进行断言来确保接口符合预期行为。
集成测试:Postman 可以用于集成测试,测试多个接口的集成和功能是否正常协作。
协作与分享:Postman 允许团队成员协作共享接口文档、测试用例、环境变量等信息,提高团队的协作效率。
Mock 服务器:Postman 可以生成 Mock 服务器,用于模拟外部服务或组件,帮助开发人员独立进行开发和测试。
环境管理:Postman 可以管理多个环境,如开发、测试、生产等,便于在不同环境之间切换测试。
数据驱动测试:Postman 支持通过 CSV 文件等数据驱动方式进行测试,提高用例覆盖范围和复用性。
3.Postman 安装
可以进入 Postman 官方网站自行选择系统下载安装:
Postman 官方网站:https://www.Postman.com/
- Home:进入登录注册页面
- Workspaces:选择工作区域(会员功能)
- Reports:测试报告(付费功能)
- Explore:探索 Postman 更多功能
- 搜索框:快速检索过滤
- 右侧:系统设置区域
- Collections:测试集
- APIs:创建 API(需要注册)
- Environments:管理环境
- Mock Servers:提供 mock 服务
- Monitors:监视器
- History:历史记录
- 顶部环境信息
- 请求配置区域
- 响应查看区域
- 查看当前使用的环境
- 查看当前环境中的变量
4.请求配置区域
在此可以新建一个请求标签
提供各种请求方法(如GET、POST等),请求参数,请求header,请求执行前的设置项目,测试脚本等的配置功能
METHOD
:请求方法URL & Params
:URL
可以输入 request 的地址,Params
是对应的URL的参数。在Params
中输入参数,会自动同步到URL
。同理,URL
里面输入带有参数的地址,也会自动同步参数到Params
Send
:发送当前请求。在发送请求之后,会自动下载该请求的response。Send and Download
在发送请求后,把响应数据保存为本地的文件。Save
可以直接保存 request。也可以选择Save as
。Save as
: 可以保存 请求的名字以及简单的描述。还可以决定要不要把请求保存到Collection里面去。Authorization
如果访问的服务需要授权,这里可以设置验证方式+填写验证所需的信息,比如用户名密码。Headers
设置请求头信息。-
Body
: 设置请求的 body。 有四种方式进行设置:form-data
、urlencoded
、raw
以及binary
。POST
中要携带的请求数据可以通过body
上传。 -
form-data
:既可以上传键值对,也可以上传文件 x-www-form-urlencoded
:会将表单内的数据转换为键值对raw
:可以上传任意格式的文本,比如说Text
、JSON
、XML
、HTML
等binary
:只可以上传二进制数据,通常用来上传文件。Pre-request Script
请求前需要执行的脚本可以放置在这里。主要进行一些环境以及全局变量的设置。-
这里写测试用例的断言,会对测试结果进行一些判断。
Generate Code
可以将request转化为各种语言的代码。比如Python、JAVA、shell、HTTP等。-
Postman中 的这些前置和断言脚本都是
JavaScript
脚本,如果会JS
语法的话,是可以自己写这些脚本的,但是Postman
当中也为提前封装好了一些常用的方法,不需要去掌握JS
语法,就可以轻松使用这些预置好的脚本。 Generate Code
可以将request转化为各种语言的代码。比如Python、JAVA、shell、HTTP等。
5.Postman 基本使用
发送 GET 请求
下面使用 Postman 发送一次 GET
请求。使用学院提供的官方演练地址进行演示
https://aihealthdev.tmqyt.com/api/sino-system/feign-system/sys/synVirtualOrder
- 进入 Postman 软件界面
- 选择
GET
请求方式 - 在 URL 处填写 https://aihealthdev.tmqyt.com/api/sino-system/feign-system/sys/synVirtualOrder
- 点击
Header
,key 值填写accept
,value 填写application/JSON
- key值填写 Sino-Auth,value填写对应值
- 点击
send
按钮,查看返回内容
6.发送 POST 请求
- 请求方式:
POST
- 请求 URL:https://httpbin.ceshiren.com/post
- 请求参数
- FORM 格式:
Body
-->form-data
- JSON 格式:
Body
-->raw
-->JSON
- 文件格式:
Body
-->form-data
-->File
- FORM 格式:
7.添加 FORM 格式请求参数
- 进入 Postman 软件界面
- 选择
POST
请求方式 - 在
URL
处填 https://aihealthdev.tmqyt.com/api/sino-system/feign-system/sys/synVirtualOrder - 选择
Body--form data
,key 值填写form_key1
,value 填写form_value1
- 点击
send
按钮,查看返回内容
8.添加 JSON 格式请求参数
- 选择
Body
--raw
-
添加
JSON
内容
添加 JSON 内容
{"json_key1":"json_value1","json_key2":"json_value2"}
-
验证响应状态码
Status Code:Code is 200
pm.test("响应状态码为 200", function () { pm.response.to.have.status(200); });
status
方法中传入的值200
就是预期结果,可以把括号中的状态码改为任意需要的值,比如400
。 -
检查响应体中是否包含某个字符串
Response Body:contains string
pm.test("响应体中包含预期的字符串", function () { pm.expect(pm.response.text()).to.include("doggie"); });
-
检测 JSON 中的某个值是否等于预期的值
Response Body:JSON value check
pm.test("宠物名称为 doggie", function () { var jsonData = pm.response.json(); pm.expect(jsonData[0].name).to.eql("doggie"); });
var jsonData
是定义了一个变量,然后把响应数据经过JSON
格式化之后,赋值给了定义好的变量。然后用
expect
这个方法,把响应数据中的url
这个key
中的值提取出来,用eql
这个方法去和括号中的字符串做比较,如果这两个值是一致的,返回true
,如果不一致就返回false
。
-
验证响应体是否与某个字符串完全相同
Response Body:Is equal to a string
这是一个全量的断言,把响应的数据和一个确定的字符串去做比较,如果完全相同返回pm.test("Body is correct", function () { pm.response.to.have.body("response_body_string"); });
true
,不完全相同返回false
。
-
验证响应头信息中的 Content-Type 是否存在
Response Body:Content-Type header check
这个断言可以用来测试响应的头信息中是否包含某个字段,pm.test("Content-Type is present", function () { pm.response.to.have.header("Content-Type"); });
Content-type
可以换位其他的字段
-
验证响应时间是否小于某个值
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
,如果没有超过返回true
,超过预设的值返回false