用 AI 搭配 BDD 三階段,把「免運費門檻」寫成可執行的驗收條件

很多團隊導入 AI 之後,第一個反應是「請 AI 幫我寫 Gherkin」。結果得到一堆語法正確、內容空洞的場景,而且沒有人知道這些場景是不是產品真正想要的行為。問題不在 AI,而在跳過了 BDD 真正的核心:Discovery、Formulation、Automation 三個階段。AI 在每個階段都能幫上忙,但角色完全不同。

下面拿一個電商常見的功能來走一遍:購物車滿額免運費


階段一:Discovery — AI 當「提問機器」,人負責決定

Discovery 的目的是在寫任何東西之前,先把需求裡的模糊地帶挖出來。傳統做法是三個朋友(PO、開發、測試)一起做 Example Mapping。這一步 AI 不能取代人,因為「什麼是正確行為」的答案在 PO 腦袋裡,不在模型裡。這就是 oracle problem:如果連驗收標準都讓 AI 決定,那後面 AI 寫的程式和 AI 寫的測試就會互相背書,沒有人在把關。

但 AI 很適合扮演那個「一直問為什麼」的討厭鬼。我把使用者故事丟給它:

身為顧客,當我的購物車金額達到 1,000 元時,我希望享有免運費,這樣我會更願意湊單。

然後請它列出「這個故事有哪些沒說清楚的地方」。它回了十幾個問題,挑幾個有價值的:

  • 1,000 元是折扣前還是折扣後的金額?
  • 剛好 1,000 元算不算達標?
  • 使用優惠券後金額掉到 1,000 以下,免運費要不要取消?
  • 預購商品或訂閱商品算進門檻嗎?
  • 離島配送是否適用同樣門檻?

這些問題在 Example Mapping 的工作坊裡本來就會被問到,但 AI 可以在會前十分鐘先產出,讓三個朋友把時間花在決定答案上,而不是花在想問題上。工作坊結束後,我們得到的是人做的決定:

  • 門檻以折扣後金額計算
  • 剛好 1,000 元算達標
  • 預購商品不計入
  • 離島不在這次範圍(另開故事)

注意這一步的產出還不是 AC,而是「規則 + 具體例子 + 已決定的問題」。這才是 AC 的原料。


階段二:Formulation — AI 當「翻譯」,人負責審

Formulation 是把 Discovery 的例子轉成結構化、可讀、可執行的格式,通常是 Gherkin。這一步最適合 AI,因為它是機械式的轉換工作,而且輸入已經被人釐清過了。

我把工作坊的規則和例子餵給 AI,並附上兩個限制:每個場景只講一條規則用業務語言而不是 UI 操作。它產出:

gherkin

Feature: 購物車滿額免運費
Rule: 折扣後金額達到 1,000 元即免運費
Example: 折扣後剛好達到門檻
Given 購物車商品小計為 1,200 元
And 使用了 200 元折價券
When 結帳計算運費
Then 運費為 0 元
Example: 折扣後低於門檻
Given 購物車商品小計為 1,100 元
And 使用了 200 元折價券
When 結帳計算運費
Then 運費為 80 元
Rule: 預購商品不計入免運門檻
Example: 預購商品撐起的金額不算
Given 購物車有一般商品 600 元
And 購物車有預購商品 500 元
When 結帳計算運費
Then 運費為 80 元

這裡人要做的是審查,而不是重寫。我通常檢查三件事:

  1. 每個例子是否對應到 Discovery 的一個決定? 例如「剛好 1,000 算達標」有沒有被一個例子精準覆蓋。AI 第一版把折價後 1,000 的例子寫成了 1,200,我要求它改成剛好 1,000,因為邊界值才是這條規則的重點。
  2. 有沒有 AI 自己「補」進來的規則? 它自作主張加了一個「VIP 會員 800 元免運」的場景,工作坊根本沒討論過。這種要直接刪掉,並且提醒 AI 不要發明需求。
  3. 語言是不是 PO 看得懂的? 如果出現「點擊結帳按鈕」「呼叫 shipping API」,就要改回業務語言。

審完之後,這份 Gherkin 就是 AC。它同時是需求文件、測試案例,也是後面自動化的規格。


階段三:Automation — AI 當「工人」,規格當「老闆」

Automation 是讓 Gherkin 變成可執行的測試,接上真正的程式碼。這一步 AI 的產能最驚人,但也最容易出事:如果前面兩步沒做好,AI 會很開心地把錯的規格自動化得很漂亮。

我把 feature 檔丟給 Claude Code,請它產出 step definitions。因為場景已經用業務語言寫好,它產出的 step 也自然對應到 domain 物件,而不是綁在 UI 上:

python

@given(parsers.parse("購物車商品小計為 {amount:d} 元"))
def cart_subtotal(cart, amount):
cart.add_item(price=amount)
@given(parsers.parse("使用了 {amount:d} 元折價券"))
def apply_coupon(cart, amount):
cart.apply_coupon(amount)
@when("結帳計算運費")
def calculate_shipping(cart, context):
context["fee"] = ShippingCalculator().calculate(cart)
@then(parsers.parse("運費為 {fee:d} 元"))
def assert_fee(context, fee):
assert context["fee"] == fee

這時候測試是紅的,因為功能還沒寫。接著才請 AI 實作 ShippingCalculator,直到所有場景轉綠。順序很重要:先有人審過的規格,再有測試,最後才有實作。這樣 AI 寫出來的程式碼是被規格約束的,而不是規格反過來遷就程式碼。


三個階段,三種分工

階段AI 的角色人的角色產出
Discovery提出問題、找出模糊處做決定、定義正確行為規則、例子、已釐清的問題
Formulation把例子翻譯成 Gherkin審查、刪除 AI 發明的內容驗收條件(AC)
Automation產生 step definitions 與實作確認順序:規格→測試→程式可執行的規格

AI 讓後兩個階段快了好幾倍,這反而讓第一個階段變得更重要。因為當產生程式碼幾乎免費時,瓶頸就移到了「我們到底想要什麼行為」。BDD 的三階段正好把這個問題留在人手上,把其他機械式的工作交給 AI。

這才是「用 AI 做 BDD」該有的樣子:不是讓 AI 替你想需求,而是讓你有更多時間去想需求。

發表迴響

探索更多來自 轉念學 - 敏捷三叔公的學習之旅 的內容

立即訂閱即可持續閱讀,還能取得所有封存文章。

繼續閱讀