SpecFormula AI
ISA後端指令

ResponseValidate

驗證 HTTP API 回應的正確性

ResponseValidate 讓你在一個步驟中同時驗證 HTTP 狀態碼與回應內容,支援 DataTable 和 JSON 兩種格式。

基本用法

Then 新增待辦事項(201)回應, with table:
  | >todo1.id | userId    | title  | completed |
  | <todoId   | $Alice.id | 買牛奶 | false     |

這段指令會:

  1. 驗證 HTTP 狀態碼為 201
  2. 驗證回應 JSON 中的欄位值
  3. 從回應中擷取 todoId,存入變數 todo1.id

兩種格式

格式適用場景
DataTable欄位級驗證,支援變數擷取
DocString JSON完整 JSON 結構驗證

JSON 格式注意事項:符號系統的表達式($變數、&CAS 約束、@時間符號、>/<擷取鍵)不可放在 JSON 字串引號 "" 內,否則會被視為純字串。

{ "todoId": $todo1.id }    // 正確:符號在引號外
{ "todoId": "$todo1.id" }  // 錯誤:符號被引號包裹,視為純字串

DataTable 格式

Then 查詢待辦事項(200)回應, with table:
  | todoId    | title  | completed |
  | $todo1.id | 買牛奶 | false     |

JSON 格式

Then 查詢待辦事項(200)回應為, with JSON:
  """json
  {
    "todoId": $todo1.id,
    "title": "買牛奶",
    "completed": false
  }
  """

巢狀路徑

支援 dot notation 和陣列索引驗證巢狀 JSON:

Then 查詢訂單(200)回應, with table:
  | data.order.id | data.items[0].name | data.items[1].name |
  | $order1.id    | 商品A              | 商品B              |

Key 含 . 的逃脫語法

當 JSON key 本身包含 . 字元時,使用 ["..."] bracket notation 避免被誤拆為多層巢狀:

Then 查詢設定(200)回應, with table:
  | content.["btn.save"] | content.["btn.cancel"] |
  | 儲存                  | 取消                    |

Response Header 驗證

使用 H: 前綴驗證回應中的 HTTP Header 值:

# DataTable
Then 新增資源(201)回應, with table:
  | H:Location       | id |
  | /api/resources/1 | 1  |

# JSON
Then 新增資源(201)回應為, with JSON:
  """json
  {
    H"Location": "/api/resources/1",
    "id": 1
  }
  """

裸值與頂層陣列 Response Body

當 API 回傳裸值(如 true42)或頂層陣列時,使用 B: 標記整個 response body:

# 裸值驗證
Then 查詢資源狀態(200)回應為, with JSON:
  """json
  { B: true }
  """

# 頂層陣列驗證 + Response Header
Then 批次新增資源(201)回應為, with JSON:
  """json
  {
    H"X-Total-Count": "2",
    B: [
      { "id": 1, "name": "資源A" },
      { "id": 2, "name": "資源B" }
    ]
  }
  """

變數擷取

使用 >< 在同一欄中上下配對:header 放變數名稱(>),row 放回應中的來源欄位(<)。

Then 登入(200)回應, with table:
  | >userToken | >userId |
  | <token     | <id     |

執行後:

  • userToken = 回應中的 token
  • userId = 回應中的 id

引用變數

使用 $variable 引用先前儲存的變數進行比對:

Then 查詢使用者(200)回應, with table:
  | userId    | name  |
  | $Alice.id | Alice |

CAS 約束驗證

使用 CAS 約束進行彈性驗證:

Then 查詢訂單(200)回應, with table:
  | orderId  | amount     | status                     | createdAt                        |
  | &isNum   | &gt(1000)  | &oneOf("pending","active") | &sameTime("2026-01-27T10:00:00") |

常用約束:

  • &isNum&isStr&isNull — 型別檢查
  • &gt()&lt()&between() — 數值範圍
  • &contains()&startsWith() — 字串匹配
  • &sameTime() — 時間比對

完整約束清單請參考 CAS-System

驗證流程

ResponseValidate 依序執行四層驗證:

  1. HTTP Status Code:狀態碼不匹配則直接失敗
  2. JSON 結構比對:遞迴比較 JSON 節點
  3. 值層驗證:數值比較、CAS 約束、變數解析
  4. Schema 驗證:對照 API Spec 定義檢查型別

錯誤處理

Lint 階段

錯誤說明
欄位不存在欄位名稱在 Response Schema 中找不到
擷取欄位不存在< 指定的欄位在 Response Schema 中找不到

執行階段

錯誤說明
狀態碼不匹配實際狀態碼與預期不符
欄位值不匹配欄位值與預期不一致
JSON 結構不匹配陣列長度、物件欄位不符
Schema 驗證失敗不符合 API Spec Schema 定義

完整範例

Feature: 更新待辦事項

  Background:
    # TimeControl 指令(參見 TimeControl 文件)
    Given 現在時間為 "2026-01-27T10:00:00"

    # EntitySetup 指令(參見 EntitySetup 文件)
    Given 準備一個使用者, with table:
      | >Alice.id | name  | email             | status |
      | <userId   | Alice | alice@example.com | ACTIVE |

  Example: 更新待辦事項標題

    # ApiCall 指令(參見 ApiCall 文件)
    When (UID="$Alice.id") 新增待辦事項, call table:
      | >todo1.id | title  |
      | <todoId   | 買牛奶 |
    When (UID="$Alice.id") 更新待辦事項, call table:
      | P:todoId  | title  |
      | $todo1.id | 買豆漿 |

    # ResponseValidate 指令 — 驗證狀態碼與回應欄位
    # $todo1.id:引用先前擷取的變數
    # &sameTime(...):CAS 時間約束,驗證時間值
    Then 更新待辦事項(200)回應, with table:
      | todoId    | title  | completed | updatedAt                        |
      | $todo1.id | 買豆漿 | false     | &sameTime("2026-01-27T10:00:00") |

目錄