4. RESTGo 契约定义:契约文件结构、YAML/JSON 契约格式、请求/响应定义、匹配规则
RESTGo 契约是压测与校验的核心载体,它同时描述了“如何构造请求”与“如何校验响应”。本章将深入契约文件的物理结构、两种序列化格式(YAML / JSON)、请求与响应的完整定义,以及决定校验成败的匹配规则体系。
4.1 契约文件结构
一个标准的 RESTGo 契约文件遵循分层结构,顶层包含契约元信息、请求模板和响应校验规则三大部分。文件扩展名通常为 .restgo.yaml 或 .restgo.json。
推荐实践:每个接口对应一个独立的契约文件,文件名与接口路径或操作名称保持一致,例如
create-user.restgo.yaml。
| 层级 | 字段 | 说明 | 是否必填 |
|---|---|---|---|
| 元信息 | name |
契约名称,用于日志与报告标识 | 是 |
| 元信息 | version |
契约版本号,支持语义化版本 | 否 |
| 元信息 | description |
接口功能描述 | 否 |
| 请求定义 | request |
包含 method、path、headers、body 等 | 是 |
| 响应校验 | response |
包含 status、headers、body 校验规则 | 是 |
| 变量定义 | variables |
全局变量或动态参数占位符 | 否 |
4.2 YAML 与 JSON 契约格式
RESTGo 同时支持 YAML 和 JSON 两种序列化格式。YAML 因其可读性高、支持注释,被推荐用于开发阶段的契约编写;JSON 则更适合自动化生成或与 CI/CD 工具链集成。
4.2.1 YAML 格式示例
name: "创建用户接口"
version: "1.0.0"
description: "POST /api/v1/users 创建新用户"
variables:
baseUrl: "https://api.example.com"
timestamp: "{{now}}"
request:
method: POST
path: /api/v1/users
headers:
Content-Type: application/json
Authorization: Bearer {{token}}
body:
name: "张三"
email: "zhangsan@example.com"
role: "admin"
response:
status: 201
headers:
Content-Type: application/json
body:
- match: exact
path: $.code
value: 0
- match: type
path: $.data.id
value: integer
- match: regex
path: $.data.email
value: "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$"
4.2.2 JSON 格式示例
{
"name": "创建用户接口",
"version": "1.0.0",
"description": "POST /api/v1/users 创建新用户",
"variables": {
"baseUrl": "https://api.example.com",
"timestamp": "{{now}}"
},
"request": {
"method": "POST",
"path": "/api/v1/users",
"headers": {
"Content-Type": "application/json",
"Authorization": "Bearer {{token}}"
},
"body": {
"name": "张三",
"email": "zhangsan@example.com",
"role": "admin"
}
},
"response": {
"status": 201,
"headers": {
"Content-Type": "application/json"
},
"body": [
{ "match": "exact", "path": "$.code", "value": 0 },
{ "match": "type", "path": "$.data.id", "value": "integer" },
{ "match": "regex", "path": "$.data.email", "value": "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$" }
]
}
}
格式选择建议:YAML 适合人工编写与版本对比;JSON 适合程序生成与跨语言解析。RESTGo 引擎内部统一将 YAML 解析为相同的内存结构,两种格式在运行时性能上无差异。
4.3 请求定义详解
请求定义(request)是压测引擎构造 HTTP 请求的依据,包含以下核心字段:
| 字段 | 类型 | 说明 | 示例 |
|---|---|---|---|
method |
string | HTTP 方法,支持 GET/POST/PUT/DELETE/PATCH | POST |
path |
string | 接口路径,支持路径参数占位符 | /api/v1/users/{{userId}} |
headers |
map | 请求头键值对,支持变量注入 | Authorization: Bearer {{token}} |
query |
map | URL 查询参数 | page: 1, size: 20 |
body |
any | 请求体,支持 JSON 对象、字符串、Form 表单 | {"name": "张三"} |
bodyType |
string | 请求体类型,可选 json / form / raw | json |
4.4 响应校验定义
响应校验(response)定义了压测通过后对返回结果的断言规则。RESTGo 支持对状态码、响应头和响应体三个维度的校验。
4.4.1 状态码校验
status 字段支持精确值或范围匹配:
# 精确匹配
status: 200
# 范围匹配(2xx 系列)
status: 2xx
# 多值匹配
status: [200, 201, 202]
4.4.2 响应头校验
headers 字段支持键值对精确匹配或正则匹配:
response:
headers:
Content-Type: application/json
X-Request-Id: "{{regex:[a-f0-9-]{36}}}"
4.4.3 响应体校验规则
body 字段是一个规则数组,每条规则包含匹配类型、JSON Path 和期望值。
4.5 匹配规则体系
匹配规则是 RESTGo 校验引擎的核心能力,决定了如何将实际响应值与契约中的期望值进行比较。RESTGo 支持以下 6 种匹配规则:
| 规则名称 | 关键字 | 说明 | 适用场景 |
|---|---|---|---|
| 精确匹配 | exact |
实际值必须与期望值完全相等(类型+值) | 状态码、固定枚举值 |
| 类型匹配 | type |
校验值的类型,支持 string / integer / number / boolean / array / object / null | 字段类型约束 |
| 正则匹配 | regex |
使用正则表达式校验字符串格式 | 邮箱、手机号、UUID 格式 |
| 范围匹配 | range |
校验数值是否在 [min, max] 区间内 | 分页总数、年龄范围 |
| 长度匹配 | length |
校验数组或字符串的长度 | 列表返回数量、字符串长度 |
| 存在性匹配 | exists |
校验字段是否存在(true/false) | 可选字段的必填校验 |
4.5.1 规则组合示例
response:
status: 200
body:
# 精确匹配业务码
- match: exact
path: $.code
value: 0
# 类型匹配 data.id 必须为整数
- match: type
path: $.data.id
value: integer
# 正则匹配邮箱格式
- match: regex
path: $.data.email
value: "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$"
# 范围匹配年龄
- match: range
path: $.data.age
value: [18, 60]
# 长度匹配 tags 数组
- match: length
path: $.data.tags
value: [1, 10]
# 存在性匹配 profile 字段
- match: exists
path: $.data.profile
value: true
注意:当一条规则匹配失败时,RESTGo 引擎会立即记录失败详情并继续执行后续规则,最终返回所有规则的校验结果汇总。这有助于在一次压测中暴露多个接口问题。
4.6 JSON Path 表达式
RESTGo 使用 JSON Path 语法定位响应体中的字段。支持的语法子集如下:
| 表达式 | 说明 | 示例 |
|---|---|---|
$ |
根对象 | $ |
$.key |
直接子属性 | $.data |
$.key1.key2 |
嵌套属性 | $.data.user.name |
$.arr[*] |
数组所有元素 | $.items[*].id |
$.arr[0] |
数组指定索引 | $.items[0] |
$.arr[?(@.key==value)] |
过滤条件 | $.items[?(@.type=="admin")] |
调试技巧:在编写复杂 JSON Path 时,可以使用 RESTGo 提供的
restgo validate 命令对契约文件进行预校验,引擎会输出 JSON Path 的解析结果和示例匹配情况。
4.7 变量与动态参数
契约中的变量系统支持在请求和响应中注入动态值,增强契约的灵活性和复用性。
| 变量类型 | 语法 | 说明 |
|---|---|---|
| 静态变量 | {{变量名}} |
从 variables 段读取固定值 |
| 内置函数 | {{now}} |
当前时间戳(毫秒) |
| 内置函数 | {{uuid}} |
生成随机 UUID v4 |
| 内置函数 | {{randomInt(min,max)}} |
生成指定范围随机整数 |
| 上下文变量 | {{$prevResponse.$.data.id}} |
引用前一个接口的响应字段 |
# 使用上下文变量实现接口链式调用
variables:
baseUrl: "https://api.example.com"
request:
method: POST
path: /api/v1/orders
body:
userId: "{{$prevResponse.$.data.userId}}"
productId: "{{$prevResponse.$.data.productId}}"
quantity: "{{randomInt(1,10)}}"
response:
status: 201
body:
- match: exact
path: $.code
value: 0
- match: type
path: $.data.orderId
value: integer
通过本章的学习,你已经掌握了 RESTGo 契约的完整定义方法。从文件结构到 YAML/JSON 格式,从请求构造到响应校验,再到灵活的匹配规则和变量系统,这些知识将为你后续进行契约压测与自动化校验打下坚实基础。