1
0
Files
DiAL/openspec/specs/expect-body-checkers/spec.md
lanyuanxiaoyao 60a54b483f refactor: expect 类型模型重构,Raw/Resolved 双层分离与断言基础设施内聚
- 重命名 ContentRules→ContentExpectations, KeyValueExpect→KeyedExpectations
- 新增 Raw/Resolved 双层模型:resolve 阶段物化为执行计划,store 持久化 Raw 快照
- HTTP body 按需读取:status/headers 失败或无 body expectation 时不读取 body
- 新增 displayValueExpectation() 解包 failure.expected 用户可读展示
- 修复 checkEarlyTimeout 独立 lte/lt 检查,修复 KeyedExpectations JSON Schema
- 新增 expect/value.ts(resolve/check/display)、keyed.ts、content.ts、headers.ts、status.ts
- 删除旧 normalize.ts/matcher.ts/validate-matcher.ts/key-value.ts
- 更新 DEVELOPMENT.md:expect 五层管线表、displayValueExpectation、1.7↔1.10 交叉引用
- 同步 13 个 main specs,归档 refactor-expect-type-model 变更(62/62 tasks)
2026-05-20 16:12:48 +08:00

13 KiB
Raw Blame History

Purpose

定义 HTTP 拨测中响应体校验方法集contains/regex/json/css/xpath、操作符系统和响应头校验的行为规范。

Requirements

Requirement: 响应体多种校验方法

系统 SHALL 支持通过共享 ContentExpectations 对 HTTP 响应体进行有序内容校验。expect.body MUST 为 expectation 数组。每个 expectation SHALL 为直接 ValueMatcher,或 jsoncssxpath extractor expectation 之一。直接 matcher SHALL 作用于完整响应体文本。json SHALL 解析响应体为 JSON 并用 JSONPath 子集提取值。css SHALL 使用 CSS selector 从 HTML 中提取元素文本或属性。xpath SHALL 使用 XPath 从 XML/HTML 中提取节点值。Extractor 未配置 matcher 时resolve 阶段 SHALL 将其 matcher 物化为 {exists: true}

Scenario: contains 子串匹配

  • WHEN HTTP target 配置 expect.body: [{contains: "healthy"}],且响应体包含 "healthy"
  • THEN 系统 SHALL 判定该 body expectation 通过

Scenario: regex 正则匹配

  • WHEN HTTP target 配置 expect.body: [{regex: '"status"\\s*:\\s*"ok"'}],且响应体匹配该正则
  • THEN 系统 SHALL 判定该 body expectation 通过

Scenario: json JSONPath 等值匹配

  • WHEN HTTP target 配置 expect.body: [{json: {path: "$.status", equals: "ok"}}],且响应 JSON 中 $.status 值为 "ok"
  • THEN 系统 SHALL 判定该 body expectation 通过

Scenario: json JSONPath 存在性匹配

  • WHEN HTTP target 配置 expect.body: [{json: {path: "$.status"}}],且响应 JSON 中存在 $.status
  • THEN resolve 阶段 SHALL 将该 expectation 按 exists: true 语义物化并在运行期判定通过

Scenario: css 选择器匹配

  • WHEN HTTP target 配置 expect.body: [{css: {selector: "div#health", equals: "OK"}}],且 HTML 中存在 div#health 元素文本为 "OK"
  • THEN 系统 SHALL 判定该 body expectation 通过

Scenario: css 选择器匹配属性值

  • WHEN HTTP target 配置 css expectation 带 attr: "content" 用于提取属性,且属性值匹配期望
  • THEN 系统 SHALL 判定该 body expectation 通过

Scenario: xpath 表达式匹配

  • WHEN HTTP target 配置 expect.body: [{xpath: {path: "/root/status/text()", equals: "ok"}}],且 XML 中 /root/status 节点文本为 "ok"
  • THEN 系统 SHALL 判定该 body expectation 通过

Scenario: 提取器无匹配目标失败

  • WHEN HTTP target 配置了 json、css 或 xpath expectation 且对应路径、元素或节点不存在,并且 expectation 未配置 exists: false
  • THEN 系统 SHALL 判定 matched 为 false

Requirement: 多种 body 校验方法 AND 组合

系统 SHALL 支持在 expect.body 数组中同时配置多条内容 expectation所有 expectation 均通过时 matched 方为 true。系统 SHALL 按数组顺序执行 expectation任一 expectation 失败后 MUST NOT 继续执行后续 expectation。

Scenario: 多种方法全部通过

  • WHEN HTTP target 的 expect.body 数组依次配置 contains、json、regex且全部通过
  • THEN 系统 SHALL 判定 matched 为 true

Scenario: 多种方法任一失败

  • WHEN HTTP target 的 expect.body 数组第一条 contains 不通过,后续还有 json expectation
  • THEN 系统 SHALL 判定 matched 为 false且不再检查后续 json expectation

Scenario: 直接 matcher 多字段组合

  • WHEN HTTP target 配置 expect.body: [{contains: "ok", regex: "status"}],且响应体同时满足 contains 和 regex
  • THEN 系统 SHALL 判定该 expectation 通过

Requirement: 操作符系统

系统 SHALL 支持通过共享 ValueMatcher 对提取值和文本值进行比较:equals(深度等值)、contains(子串包含)、regex(正则匹配)、empty(空值判断)、exists(存在性判断)、gte/lte/gt/lt(数值比较)。系统 MUST NOT 支持旧 match 字段。

Scenario: equals 匹配 JSON value

  • WHEN 配置 {equals: {status: "ok"}},且实际值为相同 JSON object
  • THEN 系统 SHALL 使用深度相等判定通过

Scenario: 显式 contains matcher

  • WHEN 配置 {contains: "success"},且实际值字符串化后包含 "success"
  • THEN 系统 SHALL 判定该规则通过

Scenario: 显式 regex matcher

  • WHEN 配置 {regex: '\\d+\\.\\d+\\.\\d+'},且实际值字符串化后匹配该正则
  • THEN 系统 SHALL 判定该规则通过

Scenario: empty matcher 判断为空

  • WHEN 配置 {empty: true},且实际值为空数组 []
  • THEN 系统 SHALL 判定该规则通过

Scenario: exists matcher 判断不存在

  • WHEN 配置 {exists: false},且实际值为 undefined
  • THEN 系统 SHALL 判定该规则通过

Scenario: 数值比较 matcher

  • WHEN 配置 {gt: 0, lt: 1000},且实际值为 500
  • THEN 系统 SHALL 对同一字段进行多 matcher 复合比较,全部通过则该规则通过

Requirement: 响应头校验

系统 SHALL 支持通过共享 KeyedExpectations 配置 expect.headers 对 HTTP 响应头进行键值断言header 名称匹配 MUST 不区分大小写。header 期望值 MUST 为 RawValueExpectationprimitive 字面量 SHALL 在 resolve 阶段等价为 {equals: <value>}

Scenario: 响应头字面量匹配

  • WHEN HTTP target 配置 expect.headers: {"Content-Type": "application/json"},且响应包含该 header 且值精确匹配
  • THEN 系统 SHALL 判定 headers 阶段通过

Scenario: 响应头 matcher 匹配

  • WHEN HTTP target 配置 expect.headers: {"Content-Type": {contains: "application/json"}},且响应 header 值包含该文本
  • THEN 系统 SHALL 判定 headers 阶段通过

Scenario: 响应头缺失

  • WHEN HTTP target 配置了某个 header 但响应中不存在该 header且未配置 exists: false
  • THEN 系统 SHALL 判定 matched 为 false

Requirement: 结构化 expect 失败信息

系统 SHALL 在任一 expect 规则失败时生成结构化 failure用于标识失败阶段、规则路径、期望值、实际值和可读错误信息。actual 值 SHALL 在构造时截断至不超过 200 字符超出部分以省略标记和总字符数替代。expected 值不截断。

Scenario: body 规则失败信息

  • WHEN HTTP target 的 expect.body[1].json 规则失败
  • THEN failure SHALL 包含 kind=mismatch、phase=body、path 指向 expect.body[1],并包含 message

Scenario: actual 值截断

  • WHEN 失败规则的实际值为字符串且长度超过 200 字符
  • THEN failure.actual SHALL 为前 200 字符加 …(共 N 字符) 后缀,其中 N 为原始总字符数

Scenario: actual 值未超限

  • WHEN 失败规则的实际值为字符串且长度不超过 200 字符
  • THEN failure.actual SHALL 保留完整原始值,不做截断

Scenario: actual 值为对象或数组

  • WHEN 失败规则的实际值为对象或数组,且 JSON 序列化后长度超过 200 字符
  • THEN failure.actual SHALL 为序列化后前 200 字符加 …(共 N 字符) 后缀

Scenario: actual 值为标量

  • WHEN 失败规则的实际值为 number、boolean、null 或 undefined
  • THEN failure.actual SHALL 保留原始值,不做截断

Requirement: 状态码范围匹配

系统 SHALL 支持在 expect.status 数组中使用范围模式字符串("1xx""2xx""3xx""4xx""5xx"),与精确数字混合使用。范围模式 SHALL 匹配对应百位段内的所有状态码。其他范围模式 SHALL 在启动期配置校验失败。

Scenario: 1xx 范围匹配

  • WHEN HTTP target 配置 expect.status: ["1xx"],且响应状态码为 101
  • THEN 系统 SHALL 判定状态码匹配

Scenario: 2xx 范围匹配

  • WHEN HTTP target 配置 expect.status: ["2xx"],且响应状态码为 200
  • THEN 系统 SHALL 判定状态码匹配

Scenario: 2xx 范围匹配 204

  • WHEN HTTP target 配置 expect.status: ["2xx"],且响应状态码为 204
  • THEN 系统 SHALL 判定状态码匹配

Scenario: 2xx 范围不匹配 301

  • WHEN HTTP target 配置 expect.status: ["2xx"],且响应状态码为 301
  • THEN 系统 SHALL 判定状态码不匹配

Scenario: 混合精确值与范围模式

  • WHEN HTTP target 配置 expect.status: ["2xx", 301],且响应状态码为 301
  • THEN 系统 SHALL 判定状态码匹配(精确值 301 匹配)

Scenario: 混合精确值与范围模式范围命中

  • WHEN HTTP target 配置 expect.status: ["2xx", 301],且响应状态码为 204
  • THEN 系统 SHALL 判定状态码匹配2xx 范围命中)

Scenario: 5xx 范围匹配

  • WHEN HTTP target 配置 expect.status: ["5xx"],且响应状态码为 503
  • THEN 系统 SHALL 判定状态码匹配

Scenario: 非 HTTP 范围模式启动失败

  • WHEN HTTP target 配置 expect.status: ["6xx"]
  • THEN 系统 SHALL 在启动期配置校验失败

Requirement: HTTP expect 规则启动期校验

系统 SHALL 在启动期校验 HTTP expect 中已支持字段的类型、格式、未知字段和可编译表达式。HTTP expect SHALL 只允许 statusheadersbodydurationMs 字段。expect.body MUST 为 RawContentExpectations 数组。直接 ValueMatcher 对象 MUST 至少包含一个合法 matcher。Extractor expectation MUST 只包含 jsoncssxpath 中的一种 extractor。Extractor 内部可以不配置 matcher并 SHALL 在 resolve 阶段以存在性 matcher 作为通过语义。equals matcher SHALL 支持任意 JSON value包括数组和对象。系统 SHALL 在启动期对所有 regex 执行静态 ReDoS 检测。语义校验 MUST NOT 修改 Raw HTTP expect 输入。

Scenario: body rule 使用 regex 字段

  • WHEN HTTP target 配置 expect.body: [{regex: "ok|healthy"}] 且 regex 可编译且无 ReDoS 风险
  • THEN 系统 SHALL 接受该配置,并在运行期按 regex expectation 匹配响应体

Scenario: body rule 不支持 match 字段

  • WHEN HTTP target 配置 expect.body: [{match: "ok"}]
  • THEN 系统 SHALL 在启动期配置校验失败,提示 match 是未知字段或不支持字段

Scenario: body rule 多 extractor 非法

  • WHEN HTTP target 的同一条 body expectation 同时配置 jsoncss
  • THEN 系统 SHALL 在启动期配置校验失败

Scenario: matcher regex 正则非法

  • WHEN HTTP target 的 expect.headers、body 直接 matcher 或 extractor 内部 matcher 配置了不可编译的 regex
  • THEN 系统 SHALL 在启动期配置校验失败

Scenario: matcher 数值比较类型非法

  • WHEN HTTP target 的 matcher 配置 gt、gte、lt 或 lte且对应值不是有限数字
  • THEN 系统 SHALL 在启动期配置校验失败

Scenario: matcher 布尔类型非法

  • WHEN HTTP target 的 matcher 配置 empty 或 exists且对应值不是布尔值
  • THEN 系统 SHALL 在启动期配置校验失败

Scenario: JSONPath 子集非法

  • WHEN HTTP target 的 json body expectation path 不符合系统支持的 JSONPath 子集
  • THEN 系统 SHALL 在启动期配置校验失败

Scenario: matcher 未知字段非法

  • WHEN HTTP target 的 matcher 配置了 foo: "bar" 等未知字段
  • THEN 系统 SHALL 在启动期配置校验失败

Scenario: durationMs matcher 非法

  • WHEN HTTP target 配置 expect.durationMs 不是合法 RawValueExpectation 或其中数值 matcher 不是有限数字
  • THEN 系统 SHALL 在启动期配置校验失败

Requirement: HTTP body 运行期失败结构化

系统 SHALL 将 HTTP body 运行期失败记录为结构化 CheckFailure并保留与具体 expectation 相关的 phase 和 path。响应内容不符合配置 SHALL 记录为 mismatch响应内容无法按配置解析或解码 SHALL 记录为 error。

Scenario: JSON 响应不是合法 JSON

  • WHEN HTTP target 配置 json body expectation但响应体不是合法 JSON
  • THEN 系统 SHALL 记录 failure.kind="error"failure.phase="body",且 failure.path SHALL 指向对应 json expectation

Scenario: CSS selector 无匹配元素

  • WHEN HTTP target 配置 css body expectation但响应 HTML 中无匹配元素
  • THEN 系统 SHALL 记录 failure.kind="mismatch"failure.phase="body",且 failure.path SHALL 指向对应 css expectation

Scenario: XPath 无匹配节点

  • WHEN HTTP target 配置 xpath body expectation但响应 XML/HTML 中无匹配节点
  • THEN 系统 SHALL 记录 failure.kind="mismatch"failure.phase="body",且 failure.path SHALL 指向对应 xpath expectation