接口测试为测试工程师的工作内容中相对高级的内容,可以通过抓取数据包来对程序相应进行测试,也是API自动化测试的重要内容
接口
是指系统或组件之间的交互点,通过这些交互点可以实现数据的交互(数据交互的通道)
软件接口的类型
按协议划分:http、Tcp、IP
按语言划分:C++、JAVA
按范围划分:系统之间的接口和程序内部的接口
- 系统之间的接口:多个内部系统之间的交互/内部系统与外部系统之间的交互
- 程序内部的接口:方法与方法之间,函数与函数之间,模块与模块之间的交互
接口测试
对系统或组件之间的接口进行测试,校验传递的数据正确性和逻辑依赖关系的正确性
原理
模拟客户端向服务器发送请求,服务器接收请求后进行相应的业务处理,并向客户端返回响应数据,检查响应数据是否符合预期
主要针对服务器进行测试
实现方式
工具:常见的有jmeter、Postman
代码:python+request+UnitTest
自动化接口测试:
借助工具、代码,模拟客户端发送请求,借助断言判断
HTTP协议
是一种基于请求与响应模式的,应用层的协议
特点
- 支持C/S模式
- 简单快速
- 灵活
- 无连接
- 无状态
URL(统一资源定位器)
是互联网上标准资源的地址
语法格式
协议: https
用户信息: user:password
(通常不建议使用)
主机(域名/IP): www.example.com
端口(0—65535): 8080
资源路径: /docs/index.html
查询参数(Query): search=keyword&page=1
片段标识符(Fragment): #section2
HTTP请求
请求行(Request Line):
- 格式:
METHOD /path HTTP/version
- 组成部分:
- METHOD: 请求方法,如
GET
、POST
、PUT
、DELETE
等。 - 空格
- /path: 请求的资源路径,相对于服务器根目录(也可以是资源路径的完整URL)。例如
/index.html
。 - 空格
- HTTP/version: 使用的 HTTP 协议版本,例如
HTTP/1.1
或HTTP/2.0
。
- METHOD: 请求方法,如
- 示例:
GET /index.html HTTP/1.1
请求头部(Request Headers):
- 格式:
Header-Name: Header-Value
- 说明:请求头部包含多个键值对,用于传递额外的信息,如客户端信息、请求参数、内容类型等。每个头部字段占一行,
Header-Name
和Header-Value
之间用冒号:
分隔。 - 常见的请求头:
Host
: 服务器的主机名(域名)和端口号。User-Agent
: 发出请求的客户端信息(如浏览器类型)。Accept
: 客户端接受的响应内容类型。Content-Type
: 请求体的数据类型(在 POST 请求中常用)。- application/json:JSON数据格式
- application/x-www-form-urlencoded:form表单数据
Authorization
: 用于传递认证信息。
- 示例:
Host: www.example.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)
Accept: text/html,application/xhtml+xml,application/xml;q=0.9
空行:
- 说明:请求头部后面的空行用于分隔请求头和请求体。如果请求没有请求体,这个空行也是必须的,用来标识请求头的结束。
请求体(Request Body, 可选):
- 说明:请求体包含客户端发送给服务器的数据。在
GET
请求中,通常没有请求体;在POST
、PUT
等请求中,请求体用于传递表单数据、JSON 数据、文件等。 - 示例(POST 请求中传递的表单数据):
username=johndoe&password=123456
HTTP 请求示例
以下是一个典型的 POST
请求的完整示例,用于提交登录表单数据:
POST /login HTTP/1.1
Host: www.example.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3
Content-Type: application/x-www-form-urlencoded
Content-Length: 29
//空行表示请求头数据已结束
username=johndoe&password=123456
HTTP 请求方法
- GET: 请求指定资源,通常用于请求数据,不包含请求体。
- POST: 向服务器提交数据,通常用于表单提交或上传文件。
- PUT: 上传指定资源,通常用于更新已有资源。
- DELETE: 请求服务器删除指定资源。
- HEAD: 与
GET
类似,但只请求头部信息,不返回实际内容。 - OPTIONS: 请求服务器返回支持的请求方法列表。
HTTP响应
HTTP响应是服务器对客户端请求的响应,它遵循HTTP协议以确保客户端能够正确解析服务器传回的数据,是对客户端HTTP请求的应答。典型的HTTP响应包括以下几个部分:
状态行(Status Line):
- 格式:
HTTP/version Status-Code Reason-Phrase
- 组成部分:
- HTTP/version:使用的HTTP协议版本,例如
HTTP/1.1
或HTTP/2.0
。 - Status-Code:状态码,一个三位数字,表示请求的处理结果
- 1xx:指示信息-表示请求已接受,继续处理
- 2xx:成功-表示请求已被成功接收、理解、接受
200 OK
:请求成功。
- 3xx:重定向-要完成请求必须进行更进一步的操作
301 Moved Permanently
:永久重定向。302 Found
:临时重定向。
- 4xx:客户端错误-请求有语法错误或请求无法实现
404 Not Found
:请求的资源未找到。
- 5xx:服务器端错误-服务器未能实现合法的请求
500 Internal Server Error
:服务器内部错误。
- Reason-Phrase:状态短语,是对状态码的简短描述,如
OK
、Not Found
等。
- HTTP/version:使用的HTTP协议版本,例如
响应头部(Response Headers):
- 格式:
Header-Name: Header-Value
- 说明:响应头部包含多个键值对,用于提供关于响应的附加信息,如内容类型、内容长度、服务器信息、缓存指令等。每个头部字段占一行,Header-Name和Header-Value之间用冒号
:
分隔。 - 常见的响应头:
- Content-Type: 响应体的数据类型,如
text/html
、application/json
等。 - Content-Length: 响应体的长度。
- Server: 服务器软件的名称和版本。
- Cache-Control: 缓存指令,告诉客户端如何缓存响应数据。
- Content-Type: 响应体的数据类型,如
空行:
- 说明:响应头部后面的空行用于分隔响应头和响应体。如果响应没有响应体,这个空行也是必须的,用来标识响应头的结束。
响应体(Response Body, 可选):
- 说明:响应体包含服务器返回给客户端的数据。在GET请求中,响应体通常包含请求的资源内容;在POST请求中,响应体可能包含处理结果或新创建的资源。
- 示例:如果客户端请求的是网页,响应体可能是HTML代码;如果请求的是图片,响应体则是图片的二进制数据。数值类型由响应头的Content-Type的值决定
HTTP响应示例: 以下是一个典型的HTTP响应示例,假设客户端请求了服务器上的index.html
文件:
HTTP/1.1 200 OK
Content-Type: text/html; charset=UTF-8
Content-Length: 1234
Server: Apache/2.4.7 (Ubuntu)
Cache-Control: no-cache
<!DOCTYPE html>
<html>
<head>
<title>首页</title>
</head>
<body>
<h1>欢迎来到我的网站</h1>
<p>这是首页的内容。</p>
</body>
</html>
在这个示例中,状态行为HTTP/1.1 200 OK
,表示请求成功。响应头部包括Content-Type
、Content-Length
、Server
和Cache-Control
等字段,提供了关于响应的附加信息。响应体是HTML页面的内容。
HTTP响应方法通常与请求方法相对应,但服务器可能会根据请求的具体情况返回不同的状态码和响应体。
接口风格
传统接口风格
请求方法只需要GET和POST
URL不唯一,针对同一操作可以使用不同的URL
状态码较单一,200最常见
序号 | 请求方式 | URL | 描述 | 参数/请求体示例 | 状态码 | 状态码描述 |
---|---|---|---|---|---|---|
1 | GET | http://api.example.com/getUsers | 获取用户列表 | page=1&size=10 | 200 | OK(请求成功) |
2 | POST | http://api.example.com/addUser | 创建新用户 | 表单数据:username=newuser&password=123456 | 201 | Created(已创建) |
3 | POST | http://api.example.com/updateUser | 更新用户信息 | 表单数据:userId=123&username=updateduser | 200 | OK(请求成功) |
4 | POST | http://api.example.com/deleteUser | 删除用户 | 表单数据:userId=123 | 200 | OK(请求成功) |
5 | GET | http://api.example.com/getUserById | 获取用户详细信息 | userId=123 | 200 | OK(请求成功) |
RESTful
REST(Representational State Transfer)表象化状态转变(表述性状态转变),在2000年被提出,基于HTTP、URI、XML、JSON等标准和协议,支持轻量级、跨平台、跨语言的架构设计。是Web服务的一种新的架构风格(一种思想)。如果一个架构符合REST原则,就称它为RESTful架构
序号 | 请求方式 | URL | 描述 | 参数/请求体示例 | 状态码 | 状态码描述 |
---|---|---|---|---|---|---|
1 | GET | http://api.example.com/users | 获取用户列表 | 200 | OK(请求成功) | |
2 | POST | http://api.example.com/users | 创建新用户 | JSON数据:{"username":"newuser", "password":"123456"} | 201 | Created(资源创建成功) |
3 | GET | http://api.example.com/users/{userId} | 获取特定用户信息 | 200 | OK(请求成功) | |
4 | PUT | http://api.example.com/users/{userId} | 更新特定用户信息 | JSON数据:{"username":"updateduser"} | 200 | OK(请求成功) |
5 | DELETE | http://api.example.com/users/{userId} | 删除特定用户 | 204 | No Content(资源已删除,无内容返回 |
RESTful架构特点
每一个URL代表一种资源
客户端和服务器之间,传递这种资源的某种表现层
表现层就是数据的不同表现形式,如图片,文字表现同一个数据对象
客户端通过四个HTTP动词(GET、POST、DELETE、PUT),对服务器资源进行操作,实现“表现层状态转化”
接口之间传递的数据最常用格式为JSON
接口测试流程
- 需求分析
- 主要依据需求文档
- 接口文档解析
- 一般由开发人员编写接口文档(API文档)
- 设计测试用例
- 执行测试
- 通过接口测试工具实现
- 通过编写代码实现
- 接口缺陷管理与跟踪
- 生成测试报告
- 接口自动化持续集成
接口文档
用来描述接口信息的文档,一般由开发人员编写,团队根据这个接口文档进行开发,并一直进行维护和遵守
1、能让前端开发和后端开发更好的配合,提高工作效率
2、项目迭代或者项目人员更迭时,方便后期人员查看和维护
3、方便测试人员进行接口测试
接口文档示例
基本信息
- 接口名称:用户信息查询
- 接口地址:
https://api.example.com/users
- 请求方式:
GET
- 接口描述:查询用户信息
请求参数
headers
Header名称 描述 是否必须 示例值 Authorization 用于认证的令牌或API密钥。 是 Bearer YOUR_ACCESS_TOKEN Content-Type 请求体的媒体类型。 否 application/json Accept 客户端期望接收的媒体类型。 否 application/json body
参数名 类型 是否必须 描述 userId int 是 用户ID 请求示例
GET /users?userId=123 HTTP/1.1
Host: api.example.com响应数据
- 成功响应
{
"code": 0,
"message": "success",
"data": {
"userId": 123,
"username": "exampleUser",
"email": "user@example.com"
}
}
- 失败响应
{
"code": 404,
"message": "User not found"
}错误码说明
错误码 描述 0 请求成功 404 用户未找到 500 服务器内部错误 版本信息
- 版本:1.0
- 更新日期:2024-08-12
维护人员
- 姓名:张三
- 邮箱:zhangsan@example.com
接口文档结构
- 基本信息
- 资源路径
- 请求方法
- 接口描述
- 请求参数
- 请求头
- 请求体:实现该接口使用的数据及对应类型
- 返回数据
- 成功:状态码 200
- 失败:错误码(自定义状态码)
- 码值
- 描述信息
接口文档解析
- 接口文档的解析本质:从接口文档中,找出http请求所需的数据信息请求方法
- 主要找出:请求方法、URL、请求头、请求体、响应状态码、描述
- 以上文示例为例
- 请求方法:GET
- URL:https://api.example.com/users
- 请求头:
- Authorization:Bearer YOUR_ACCESS_TOKEN
- Content-Type:application/json
- Accept:application/json
- 请求体:{“userId”:””}
- 响应状态码:0
- 错误码:
- 404
- 500
- 错误码:
接口用例设计
接口测试测试点(测试维度)
- 功能测试
- 单接口功能
- 手工测试中的单个业务模块,一般对应一个接口
- 借助工具、代码。绕开前端界面,组织接口所需要的数据,展开接口测试
- 业务场景功能
- 按照用户实际使用场景,梳理 接口业务 场景
- 组织业务场景,一般只需做正向测试即可
- 一般建议用最少的用例覆盖最多的业务场景
- 登录——搜索商品——加购物车——下单——支付——评价(一个完整的购物网站购物的场景)
- 单接口功能
- 性能测试
- 响应时长
- 吞吐量(TPS)
- 并发数
- 服务器资源使用率
- 安全测试
- 攻击安全:由专业安全测试工程师来设定
- 业务安全
- 敏感数据是否加密(密码)
- SQL注入(常见的有‘OR 1=1#’)
- 其他
设计方法与思路
与手工设计相同之处
手工测试对应的功能测试点,与接口对应的功能完全一致
与手工设计不同之处
- 手工数据测写入到输入框中的数据是否正确。接口测试测参数对应的参数值是否正确
- 接口测试,不单单对 参数值进行测试,还可以针对 参数本身进行测试
- 正向参数:
- 必选参数:所有的 必选(必填)都包含(数据库中所有的非空字段)
- 组合参数:所有的 必选+任意一个或多个可选参数
- 全部参数:所有的 必选+所有的 可选参数
- 反向参数
- 多参:多出一个或多个必选参数(可以任意指定)
- 少参:缺少一个或多个必选参数
- 无参:没有必选参数
- 错误参数:参数名输入错误
- 正向参数:
单接口测试用例
接口测试用例10要素
编号、用例名称、模块、优先级、预置条件、请求方法、URL、请求头、请求体(请求数据)、预期结果
编号 | 用例名称 | 模块 | 优先级 | 预置条件 | 请求方法 | URL | 请求头 | 请求体(请求数据) | 预期结果 |
---|---|---|---|---|---|---|---|---|---|
TC001 | 查询用户信息 | 用户信息 | 高 | 1. 用户已注册 2. 接口服务正常运行 | GET | https://api.example.com/users | Content-Type: application/json Authorization: Bearer YOUR_ACCESS_TOKEN | {“userId”: 123} | 响应状态码为200 返回用户信息:username, email等 |
TC002 | 非注册用户查询 | 用户信息 | 中 | 1. 用户未注册 2. 接口服务正常运行 | GET | https://api.example.com/users | Content-Type: application/json Authorization: Bearer YOUR_ACCESS_TOKEN | {“userId”: 99999} | 响应状态码为404 返回消息:User not found |
TC003 | 错误请求方法 | 用户信息 | 中 | 接口服务正常运行 | POST | https://api.example.com/users | Content-Type: application/json | {“userId”: 123} | 响应状态码为405 返回消息:Method Not Allowed |
TC004 | 缺少请求头 | 用户信息 | 中 | 接口服务正常运行 | GET | https://api.example.com/users | – | {“userId”: 123} | 响应状态码为400 返回消息:Missing headers |
TC005 | 无效的Authorization头 | 用户信息 | 中 | 接口服务正常运行 | GET | https://api.example.com/users | Content-Type: application/json Authorization: Bearer INVALID_TOKEN | {“userId”: 123} | 响应状态码为401 返回消息:Unauthorized |
TC006 | 超出范围的用户ID | 用户信息 | 中 | 1. 接口服务正常运行2. 用户ID有最大值限制 | GET | https://api.example.com/users | Content-Type: application/json Authorization: Bearer YOUR_ACCESS_TOKEN | {“userId”: 超出正常范围的值} | 响应状态码为400 返回消息:Invalid user ID |
TC007 | 非法格式的用户ID | 用户信息 | 中 | 接口服务正常运行 | GET | https://api.example.com/users | Content-Type: application/json Authorization: Bearer YOUR_ACCESS_TOKEN | {“userId”: “ABC”} | 响应状态码为400 返回消息:Invalid user ID format |
TC008 | 空请求体 | 用户信息 | 中 | 接口服务正常运行 | GET | https://api.example.com/users | Content-Type: application/json Authorization: Bearer YOUR_ACCESS_TOKEN | – | 响应状态码为400 返回消息:Empty request body |
TC009 | 服务不可用 | 用户信息 | 中 | 接口服务不可用 | GET | https://api.example.com/users | Content-Type: application/json Authorization: Bearer YOUR_ACCESS_TOKEN | {“userId”: 123} | 响应状态码为503 返回消息:Service Unavailable |
查询模块的测试点
- 数值
- 正向:
- 正常用户ID查询(TC001)
- 反向:
- 未注册用户ID查询(TC002)
- 超出范围的用户ID(TC006)
- 非法格式的用户ID(TC007)
- 正向:
- 参数
- 正向:
- 完整请求参数(TC001)
- 反向:
- 缺少请求头(TC004)
- 错误请求方法(TC003)
- 无效令牌信息(TC005)
- 空请求体(TC008)
- 服务不可用(TC009)
- 多参(请求体:{“userId”:”123″,”username”:”name”})
- 少参
- 错误参数(请求体:{“user”:”123″}
- 正向:
业务场景测试用例
- 用户怎么用,怎样设计业务
- 用最少的测试用例,尽量覆盖最多的接口
链接为一个示例的电商业务的接口文档业务接口文档示例 – 闲言碎语 (wfqn.xyz)
分析测试点
针对示例的业务场景:
注册——浏览商品——加入购物车——订单管理
针对这些测试点(接口)分别设计测试用例(一般而言,业务整体的接口测试用例只考虑正向用例,只考虑验证业务功能的可通性,不考虑鲁棒性)
可以参考前文的查询测试用例,笔者这里不再列出,读者感兴趣可以自行编写。
接口测试工具
目前市面上常见的接口测试工具为Postman,笔者公司要求使用Apifox,但由于测试工具的具体使用方法基本大同小异,因此对于Postman的了解仅存在于书面,后续如果有相关功能的截图/示例会以Apifox为主。
考虑到测试岗没有编写完整接口的能力需求,读者手头也不一定有能够进行测试的未使用加密协议(https)的服务器,因此可以使用网络上公开的API接口平台,如教书先生API – 提供免费接口调用平台 (oioweb.cn)、免费API,收集所有免费的API (free-api.com)
以手机号归属地查询API为例,接口文档如下图
分析该文档:
- 请求方式:GET/POST
- URL:https://api.oioweb.cn/api/common/teladress
- 请求头:
- ACCEPT:application/json
- 请求体:
- 返回码:200,400,500
打开Apifox,新建一个练习用环境,环境的前置URL设为空(如果拥有专门的测试服务器,这里应填写服务器IP+端口,方便后续测试)
新建一个接口
然后就可以针对接口进行测试了