把驗收文件變成可執行規格:用 AI 產生 Gherkin,交給 Karate 跑自動化測試
你知道專案該有測試,可能也在文件或會議裡聽過「BDD」「Gherkin」這些詞,但始終沒弄清楚它們到底是什麼、跟你平常寫的測試有什麼關係。這篇就從這裡開始:先把 BDD 跟 Gherkin 講清楚,再看怎麼讓 AI 分兩步把需求變成測試——先產生一份人人都讀得懂的驗收文件,再把它轉成 Karate 能執行的規格——最後交給 Karate 驗證系統有沒有照規格動。一份規格,同時是大家確認過的需求,也是會自己驗證的可執行測試。
先講清楚:BDD 跟 Gherkin 是什麼
如果你寫過測試,流程大概是這樣:想好要測什麼,然後用 JUnit、Jest 之類的框架,把斷言一條條寫成程式碼。這沒問題,但有個侷限——這些測試只有工程師看得懂。PM、QA、需求方想知道「這個功能到底驗了哪些情況」,沒辦法直接讀你的測試碼。
BDD(Behavior-Driven Development,行為驅動開發) 想補的就是這個落差。它的主張很單純:在動手寫程式之前,先用「一般人也讀得懂的語言」把系統『該有什麼行為』描述清楚,而且這份描述要結構化到——理論上可以直接拿來當測試的依據。這份描述,就是常說的驗收文件(描述「系統在什麼情況下、該做出什麼反應」的文件)。
那要用什麼格式寫?這就是 Gherkin 登場的地方。Gherkin 是一套寫這種行為描述的語法,核心只有三個關鍵字:
- Given(前提):在什麼情況下
- When(動作):做了什麼
- Then(預期結果):應該得到什麼
三個關鍵字把一個情境拆成「在什麼前提下,做了什麼,應該得到什麼」。它幾乎就是結構化的自然語言,不會寫程式的人也讀得懂——等一下的範例你就會看到完整長相。
重點來了:Gherkin 寫出來的這份東西,到底是文件、還是測試? 傳統上它是文件,要另外有人把它翻譯成可執行的測試碼。而這篇要講的 Karate,就是讓這份 Gherkin 文件「直接變成能跑的測試」,中間那層翻譯不用了。
但驗收文件常常最後只是個「裝飾品」
先說傳統做法卡在哪。Gherkin 場景寫得再漂亮,它終究只是文件,跟「系統真的會這樣動」之間還隔著一層——要有人把它翻譯成可執行的測試碼,而這個翻譯過程很容易跑掉。寫驗收文件的人描述的是意圖,寫測試碼的工程師描述的是實作細節,兩者一旦分家,文件很快就變成「沒人敢刪、但也沒人會更新」的裝飾品。
Karate 想解的就是這個落差。它把 Gherkin 語法直接拿來當作可執行語言。寫 feature file 的人不需要懂 Java/JS 怎麼發 HTTP request、怎麼斷言 JSON 結構,只要懂 Gherkin 跟一點 JSON。
一個最小範例:從驗收文件到 Karate feature file
光說不練沒意義,直接看一組真的會動的例子。情境是最常見的待辦事項清單(Todo List)——使用者可以新增待辦事項、標記完成、刪除。
先看一份純給人讀的驗收文件,不含任何 Karate 語法,純粹用 Gherkin 把行為描述出來(這份等一下會說明,正是讓 AI 產生的第一個產物):
Feature: 待辦事項清單 (Todo List)
作為使用者,我想要新增、完成與刪除待辦事項,
以便管理我每天要做的事。
Scenario: 新增一筆待辦事項
Given 目前待辦清單是空的
When 我新增一筆待辦事項 "買牛奶"
Then 系統應該回應新增成功
And 這筆待辦事項預設應該是未完成
Scenario: 將待辦事項標記為已完成
Given 已經有一筆待辦事項 "買牛奶"
When 我把這筆待辦事項標記為已完成
Then 這筆待辦事項的狀態應該變成已完成
Scenario: 刪除一筆待辦事項
Given 已經有一筆待辦事項 "買牛奶"
When 我刪除這筆待辦事項
Then 待辦清單裡應該再也找不到這一筆
Scenario: 刪除不存在的待辦事項應該失敗
Given 不存在 id 為 "does-not-exist" 的待辦事項
When 我嘗試刪除這筆待辦事項
Then 系統應該回應找不到資源
這份文件,PM、QA、不寫程式的人都看得懂,可以拿去跟需求方確認「我們講的是同一件事」。但它還不可執行——目前待辦清單是空的這句話,沒有任何程式知道要怎麼跑。
接下來把它翻成 Karate 版本。場景結構幾乎是一一對應,差別只在於把業務語言換成具體的 HTTP 操作:
Feature: todo API
Background:
* url baseUrl
Given path '__reset'
When method delete
Then status 204
Scenario: 新增一筆待辦事項
Given path 'todos'
And request { title: '買牛奶' }
When method post
Then status 201
And match response == { id: '#string', title: '買牛奶', done: false }
Scenario: 將待辦事項標記為已完成
Given path 'todos'
And request { title: '買牛奶' }
When method post
Then status 201
* def todoId = response.id
Given path 'todos', todoId
And request { done: true }
When method patch
Then status 200
And match response.done == true
Scenario: 刪除一筆待辦事項
Given path 'todos'
And request { title: '買牛奶' }
When method post
Then status 201
* def todoId = response.id
Given path 'todos', todoId
When method delete
Then status 204
Given path 'todos', todoId
When method get
Then status 404
Scenario: 刪除不存在的待辦事項應該失敗
Given path 'todos', 'does-not-exist'
When method delete
Then status 404
對照著看會發現,Given 已經有一筆待辦事項「買牛奶」變成了先 POST 建立一次;Then 這筆待辦事項的狀態應該變成已完成變成了 match response.done == true。場景命名、場景數量、case 的順序完全沒變,只是每一步從敘述變成了動作。這就是 Karate feature file 讀起來不像「測試程式碼」、而像「會動的文件」的原因。
第一個 scenario 裡的 match response == { id: '#string', title: '買牛奶', done: false } 還用到了 Karate 的模糊比對符號:#string 不是字面值,意思是「這個欄位只要是字串就算過」。因為 id 是伺服器隨機產生的,沒辦法寫死比對精確值,這時就用型態比對取代。同樣的符號還有 #number、#boolean、#regex 等,遇到只在乎型態或格式、不在乎具體數值的欄位時很好用。
讓 AI 分兩步:先寫驗收文件,再轉成 Karate 規格
上面那兩段 Gherkin 不是憑空冒出來的。實際流程裡,AI 會幫你做兩件不同的事,中間各有一道「人來確認」的關卡,最後才輪到 Karate 執行:
第一步:讓 AI 產生 spec by example 的驗收文件。
把需求、API 規格丟給 AI,讓它草擬出前面那份純給人讀的 Gherkin 驗收文件——所謂 spec by example,就是用一個個具體範例把抽象規則講清楚。這份文件的讀者是 PM、PO、工程師,大家圍著同一個問題對焦:「這些場景有沒有驗到點上?需求真的是這樣嗎?邊界情況漏了沒?」 這一關確認的是「我們要驗的東西對不對」,跟技術無關。AI 在這步最大的價值,是常會補上你自己沒想到的邊界情況(例如上面「刪除不存在的待辦事項」這個 case),反而把規格補得更完整。
第二步:讓 AI 把驗收文件轉成 Karate 可執行規格。
驗收文件拍板後,再讓 AI 把它轉成前面那份 Karate feature file。這步換工程師把關,要看兩件事:一是轉出來的場景要跟驗收文件對得上——場景命名、數量、順序不能跑掉,不能偷偷多驗或漏驗;二是工程面要正確——path、status code、斷言、#string 這類模糊比對符號用得對不對。AI 加速的是打字跟查語法,但「有沒有忠實對應驗收文件」「驗得對不對」最後還是工程師說了算。
最後,交給 Karate 執行。
兩份都確認過了,Karate 直接拿第二份去跑真實的 API、做斷言。到這裡分工就很清楚:AI 負責「產生」驗收文件、再「轉換」成 Karate 規格,Karate 負責「執行驗證」。 順序從「先憑空想場景、再手刻測試」變成「先有候選範例、確認後再轉、最後自動驗證」,每一關都有人看著,認知負擔卻小很多。
整條線用一張表收斂:
| 階段 | 誰來做 | 產物 | 誰確認 | 確認什麼 |
|---|---|---|---|---|
| 第一步 | AI | spec by example 驗收文件(純 Gherkin) | PM / PO / 工程師 | 有沒有驗到點上、需求對不對、邊界漏沒漏 |
| 第二步 | AI | Karate 可執行規格(feature file) | 工程師 | ① 跟驗收文件對得上 ② 工程面正確(path / status / 斷言 / 模糊比對) |
| 執行 | Karate | 測試結果 + 互動式 HTML 報表 | —(自動) | 跑真實 API、做斷言 |
Karate v2 是什麼
Karate v2.0.0 在 2026-03-26 發布,是整個框架的從頭重寫,寫這篇文章時最新版本是 2026-06-04 發布的 v2.0.10。跟 v1 比起來,幾個值得知道的變化:
- 自製 JS 引擎
karate-js:取代了原本的 GraalJS,啟動更快 - Virtual Threads:平行執行測試直接吃 Java 21+ 的 virtual thread
- W3C WebDriver:除了原本的 CDP driver,現在也支援標準 WebDriver,跨瀏覽器
- 互動式 HTML 報表:用 Alpine.js 做的 dashboard,有 timeline 視圖、tag 篩選
v2 對 v1 大致維持相容,多數 v1 寫的 feature file 不太需要改就能在 v2 跑。
安裝設定:最少需要這三個東西
- karate.jar——標準作法是從 GitHub Releases 抓對應版本:
wget https://github.com/karatelabs/karate/releases/download/v2.0.10/karate-2.0.10.jar
java -jar karate-2.0.10.jar tests/todo.feature
(官方的 npm wrapper @karatelabs/karate 目前對 v2 是壞的,這個 repo 改成用一個小腳本直接下載 standalone jar 來跑,細節看 karate-runner.js。)
- karate-config.js——放在跑測試的工作目錄,是一個回傳設定物件的 function:
function fn() {
return {
baseUrl: 'http://localhost:3000'
};
}
feature file 裡用 * url baseUrl 取這個值,要切環境就用 karate.env 在這個 function 裡面分支處理。
- 被測試的服務本身要先跑起來——Karate 測的是真實的 HTTP API,不會幫你啟動你的服務。
不只是 API:瀏覽器測試與內建報表
Karate 的範圍比單純的 API 測試大——它同時支援瀏覽器自動化,讓你在同一個 feature file 裡先用 API 建好資料,再開瀏覽器驗證畫面。
提一個版本細節:v2 現在能用的是 CDP(速度快,限 Chrome/Edge)跟 W3C WebDriver(跨瀏覽器,但拿不到 CDP 的進階能力)。這個 repo 的 tests/todo-ui.feature 用 CDP driver 對 public/ 底下的待辦清單頁面寫了一組 UI 測試,完整語法可以直接參考。
跑完測試直接在 target/karate-reports 生出互動式 HTML 報表,失敗的步驟自動截圖,可以依 tag 篩選、展開巢狀的 call,不需要再另外接 Allure 之類的工具。
報表長什麼樣子
整套 npm test 跑完,Summary 頁面會列出每個 feature 的通過率跟耗時:

點進某個 feature,可以看到每個 scenario 展開後的完整步驟,連 UI 測試裡的 driver、input、click 這些動作也都一步一步記錄下來:

另外還有一個 Timeline 視圖,把所有 scenario 依執行順序畫成時間軸,一眼就看得出哪個 scenario 拖慢了整體時間(這個例子裡,UI 測試啟動瀏覽器的那個 scenario 明顯比其他 API scenario 慢很多):

小結
回到最開始那條線:AI 先產生一份人人都讀得懂、PM 跟工程師一起確認過的 spec by example 驗收文件,再把它轉成跟文件對得上、工程面也正確的 Karate 可執行規格,最後 Karate 拿它去驗證系統——讓驗收文件不再是擺著好看的裝飾品。
現在 Karate v2 把安裝、設定都簡化到剩幾個檔案,瀏覽器測試跟 API 測試共用同一套 Gherkin 語法,還有內建的互動式報表,完整的工具鏈搭配 AI 非常好用。
上面這組範例的完整可執行程式碼放在這個 Github repo,README 也寫好了,試用看看吧。
參考來源: