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 全局变量或动态参数占位符 否
RESTGo 契约文件结构 契约文件 元信息 (metadata) 请求定义 (request) 响应校验 (response) 变量定义 (variables) name version method path status body 规则 动态变量 契约文件组织原则 • 请求与响应分离:request 只描述发送内容,response 只描述校验规则 • 变量定义支持运行时注入,如 {{userId}}、{{timestamp}} • 元信息中的 name 字段在压测报告中作为接口标识

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 和期望值。

响应体校验规则执行流程 解析响应 JSON 遍历 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 格式,从请求构造到响应校验,再到灵活的匹配规则和变量系统,这些知识将为你后续进行契约压测与自动化校验打下坚实基础。