AI x BDD 軟體全自動化開發術 - (2): 靠「可執行規格」,未來的程式語言就是中文和英文沒錯!
就是這「可執行規格」,讓行為驅動開發 (BDD) 變成 Vibe Coding 時代下的寵兒!如果一份「需求規格」可以作為測試被執行,那只要我們訂好規格,就能命令 AI 開發出完全符合規格的程式碼,你不再需要花一堆時間擔心 AI 寫錯 Code,因為全部都被「可執行規格」這份「測試」給保護了。
上一篇文我們介紹了 行為驅動開發 (Behavior-Driven Development, BDD) 開發方法中最關鍵的「實例化需求(Spec by Example)」以及它在軟體開發中的關鍵價值。
這一篇,我們要實際動手,將前面提到的實例化需求,轉化為「可執行規格(Executable Specification)」。未來,人類只需要撰寫這種規格,就能讓 AI 自動產出正確的程式碼,不再需要手動寫程式。
可執行規格 (Executable Specification) 是什麼?
首先,長話短說,可執行規格是一種黑箱的自動化測試 (Automated Test)!
所謂黑箱測試,指的是:「這種測試不會涉及任何程式細節或技術實作」,它只關心一件事:當系統收到某個輸入時,輸出的結果和系統在執行行為後的狀態是不是對的。
正因為它不涉及技術細節,所以你可以試著把讓這些測試寫好看一點,讓它們看起來就像是在寫業務邏輯、像在描述需求一樣。
換句話說啊,如果讓沒技術背景的人來看你寫的「測試」,這些人還能完全看得懂、不只看得懂還知道怎麼修改的話,那這樣的測試就叫做「可執行規格」(Executable Specification)!
所以,你現在應該懂「可執行規格」這個名字為什麼這樣取了吧?
因為它有兩個特點:
- 可以被執行(就像一般自動化測試那樣)
- 長得像需求規格(而不是像難懂的程式)
這兩個特點合在一起,就是「可執行規格」。
快跟我說:「可執行規格」長什麼樣子?
「如果你希望測試長得像需求規格,那你就真的去寫一份需求規格就好啦!」
可執行規格——其實就是大家想像中未來世界的模樣。
不都說未來的程式語言就是「中文」和「英文」嗎?你只要動動嘴、說出需求,AI 就會幫你寫好整套系統。
沒錯,可執行規格就是用中文/英文「說出來的一口好測試」。
它不需要你寫程式,只要把需求說清楚、寫明白,AI 就能照著實作。
不過啊,話雖如此,科技還沒厲害到能聽你亂說話還能幫你寫出對的東西。
所以你不能真的「隨便說」,而是要「用統一、結構化的格式」來描述需求,AI 才能準確理解並正確執行。
這時候,就該登場的就是 Gherkin Language。
它是一種標準化的語法規格,專門用來撰寫這種可被執行的需求描述。雖然是用自然語言寫的,但格式非常清晰有邏輯,讓人和機器都能讀得懂、跑得動。
Gherkin Language 是什麼?
Gherkin Language 認定了系統的每一道功能 (Feature),可以拆解成多種情境 (Scenario),而每個情境又可以拆解成三個行為部分:「給定 (Given)」、「當 (When)」、「結果 (Then)」:
Given
:描述前提條件When
:描述使用者的操作(也是你想要測試的操作)Then
:描述操作執行之後預期的結果
只靠這三個部分,就能描述大多數的系統功能情境。
範例:訂單優惠的可執行規格
例如,下面是一個電商優惠邏輯「滿 1000 折 100 元」的可驗收規格,用 Gherkin 寫成的可驗收規格長這樣:
Feature: 滿額折扣
Scenario: 滿 1000 折 100
Given 購物車內包含以下商品
| 商品名稱 | 數量 | 單價 |
| T-shirt | 2 | 500 |
| 褲子 | 1 | 600 |
When 結帳
Then 訂單總金額應為 1500
And 訂單應包含以下商品
| 商品名稱 | 數量 |
| T-shirt | 2 |
| 褲子 | 1 |
翻譯成中文的話就是:
- 這個功能 (Feature) 叫做「滿額折扣」
- 滿額折扣中的第一個實例情境 (Scenario) 是:
- 給定 (Given):購物車中有兩件 500 元的 T-shirt,和 1 件 600 元的褲子。
- 當 (When):我結帳之後
- 結果 (Then):
- 訂單總金額應為 1500
- 訂單應包含兩件 T-shrt 和 1 間褲子
這就是把「實例化需求」撰寫成「可執行規格」的樣子。
好,其實我現在只解釋了一半而已,你大概也只覺得「啊這不就只是一種帶著實際資料的規格驗收文件」,你憑什麼說他「可以執行」?
你說啊,水球,明明就只是個 Spec,你憑什麼說他 Executable!?
那規格要怎麼才能「執行」起來呢?靠的當然是技術!其中最關鍵的,就是 Cucumber —— 最知名的 BDD 測試框架。
用 Cucumber 實作可執行規格
Cucumber 是目前最知名的 BDD 測試框架,Gherkin Language 便是 Cucumber 採用的格式,而採用了 Gherkin Language 格式所撰寫的規格文件稱之為 Feature file。
Cucumber 會幫助你把這個 Feature file 中,每一個 Scenario 底下的 Given / When / Then 全部綁定到對應的「測試函數」上。
好比你可以使用底下這種描述方式來綁定:
@given('購物車內包含以下商品')
def given_cart_items_contains(context):
...
@when('結帳')
def when_checkout(context):
...
@then('訂單總金額應為 {expected_total:d}')
def then_total_amount_should_be(context, expected_total):
...
@then('訂單應包含以下商品')
def then_items_should_contain(context):
...
這些函數經過 Cucumber 的配置後,就能自動「綁定」到 Feature file 中對應的 Given
/ When
/ Then
步驟。舉例來說,當 Cucumber 執行 "Given 購物車內包含以下商品"
這行時,就會自動呼叫你程式中 given_cart_items_contains
這個函數。
這些與 Gherkin 步驟綁定的函數,我們稱之為 Step Definitions。
我自己習慣把它們叫做 Test Step(中文可以翻成「測試步驟」,懶一點就直接說「測試步」)。
所以你只需要依照 Given
/ When
/ Then
的順序,填入你原本測試程式中會寫的 Arrange、Act、Assert 的程式碼邏輯,就能把這份規格「變成真的、能執行的測試」。
from behave import given, when, then
@given('購物車內包含以下商品')
def given_cart_items_contains(context):
# 清空購物車資料(假設是測試用 DB)
db_session.query(CartItem).delete()
db_session.commit()
# 將給定商品加入購物車中
for row in context.table:
item = CartItem(
name=row['商品名稱'],
quantity=int(row['數量']),
price=int(row['單價']),
)
db_session.add(item)
db_session.commit()
@when('結帳')
def when_checkout(context):
# 呼叫後端結帳 API,例如 POST /api/checkout
response = requests.post("http://localhost:8000/api/checkout")
assert response.status_code == 200, f"結帳 API 呼叫失敗,狀態碼 {response.status_code}"
# 取得 API 的回應
data = response.json()
# 將回應塞進去 Cucumber context 中,用於 @then 中驗證
context.order_total = data['total']
context.order_items = data['items']
@then('訂單總金額應為 {expected_total:d}')
def then_total_amount_should_be(context, expected_total):
assert context.order_total == expected_total
@then('訂單應包含以下商品')
def then_items_should_contain(context):
for expected in context.table:
found = any(
item['name'] == expected['商品名稱'] and item['quantity'] == int(expected['數量'])
for item in context.order_items
)
assert found, f"未找到商品:{expected['商品名稱']} × {expected['數量']}"
這就是「可執行規格」的程式實作方式。
而且你要知道——測試步驟的綁定,跟測試的層級是沒有關係的。
你可以拿來寫 End-to-End 測試、Unit 測試,甚至是前端的 Component-level 測試都行,觀念通了,用在哪裡都可以套得上。
像我上面舉的範例,就是一個典型的 後端 End-to-End 測試:
- 在
Given
裡,我把給定購物車商品資料塞進資料庫 - 在
When
裡,我呼叫後端的結帳 API endpoint - 在
Then
裡,我驗證 API 回傳的訂單金額與商品明細是否正確
雖然這是後端系統的測試步驟實作,但只要你掌握這套思維模式,就能輕鬆應用到任何技術場景裡。
蛤?你說這些測試步看起來寫起來有點麻煩?
哎呀,那你一定還沒聽過「先苦後甘」這個道理!
我跟你說,這些測試步驟的程式碼,只要你寫過一次,之後可以重複用個好幾十次。每一段 Given
、When
、Then
測試步,就像是你未來所有可執行規格裡的「積木模組」,直接組合、快速覆蓋各種情境。
這些測試步驟的實作,其實可以被反覆使用超多次!
別被上面的程式碼嚇到啦,雖然一開始你得自己寫 Feature file,寫完還要自己去綁定對應的測試步驟,看起來好像有點麻煩對吧?
但你有沒有注意到——上面那幾段短短的 Given
/ When
/ Then
測試步驟,其實就已經能支援超多驗收情境了!
我們來實作看看吧!
就以「訂單優惠」這個功能為例,假如我們把這份可執行規格中所有的六個業務情境通通寫進同一個 Feature file。來,你看看底下這個完整的 Feature file,每一個情境都是真正可執行的規格,而你只寫了一次測試步驟:
Feature: 電商訂單計價優惠
作為一位購物者
我希望系統能根據優惠規則計算訂單總金額
讓我清楚知道要付多少錢,以及會收到哪些商品
Scenario: 購買單一商品,未套用任何優惠
Given 購物車內包含以下商品
| 商品名稱 | 數量 | 單價 |
| T-shirt | 1 | 500 |
When 結帳
Then 訂單總金額應為 500
And 訂單應包含以下商品
| 商品名稱 | 數量 |
| T-shirt | 1 |
Scenario: 滿 1000 折 100
Given 購物車內包含以下商品
| 商品名稱 | 數量 | 單價 |
| T-shirt | 2 | 500 |
| 褲子 | 1 | 600 |
And 已設定滿額折扣活動
| 門檻金額 | 折扣金額 |
| 1000 | 100 |
When 結帳
Then 訂單總金額應為 1500
And 訂單應包含以下商品
| 商品名稱 | 數量 |
| T-shirt | 2 |
| 褲子 | 1 |
Scenario: 化妝品買一送一(不同商品)
Given 購物車內包含以下商品
| 商品名稱 | 類別 | 數量 | 單價 |
| 口紅 | 化妝品 | 1 | 300 |
| 粉底液 | 化妝品 | 1 | 400 |
And 化妝品買一送一優惠已啟用
When 結帳
Then 訂單總金額應為 700
And 訂單應包含以下商品
| 商品名稱 | 數量 |
| 口紅 | 2 |
| 粉底液 | 2 |
Scenario: 化妝品買一送一(相同商品)
Given 購物車內包含以下商品
| 商品名稱 | 類別 | 數量 | 單價 |
| 口紅 | 化妝品 | 2 | 300 |
And 化妝品買一送一優惠已啟用
When 結帳
Then 訂單總金額應為 600
And 訂單應包含以下商品
| 商品名稱 | 數量 |
| 口紅 | 3 |
Scenario: 化妝品買一送一(與其他類別混合)
Given 購物車內包含以下商品
| 商品名稱 | 類別 | 數量 | 單價 |
| 襪子 | 服飾 | 1 | 100 |
| 口紅 | 化妝品 | 1 | 300 |
And 化妝品買一送一優惠已啟用
When 結帳
Then 訂單總金額應為 400
And 訂單應包含以下商品
| 商品名稱 | 數量 |
| 襪子 | 1 |
| 口紅 | 2 |
Scenario: 滿額折扣 + 買一送一 同時套用
Given 購物車內包含以下商品
| 商品名稱 | 類別 | 數量 | 單價 |
| T-shirt | 服飾 | 3 | 500 |
| 口紅 | 化妝品 | 1 | 300 |
And 已設定滿額折扣活動
| 門檻金額 | 折扣金額 |
| 1000 | 100 |
And 化妝品買一送一優惠已啟用
When 結帳
Then 訂單總金額應為 1700
And 訂單應包含以下商品
| 商品名稱 | 數量 |
| T-shirt | 3 |
| 口紅 | 2 |
你會發現,這些情境一被寫完全部就都可以被執行了,而且通通共用你剛剛寫的那一份測試步驟程式。你看看,你有需要為了這些更多不同的訂單優惠情境,去額外實作不同的測試步驟程式嗎?不需要啊。
而且啊,擴充規格的搞不好不是你,有可能是你老闆手賤自己修改,或是業務同事想要增加需求,但這些「缺乏技術背景」的夥伴卻完全不需要了解程式碼,就能獨立修改規格書了呢!
這件事聽起來很普通?不!你得再想一想,這件事其實是個突破。正是因為這份規格本身能執行、能驗證,加上 AI 的能力,行為驅動開發(BDD)才成為 Vibe Coding 時代的寵兒。
可執行規格,就是 Vibe Coding 的核心突破!
Vibe Coding 的核心主張是:
「我們不再需要寫程式,只要跟 AI 說清楚需求,AI 自己會寫完並確保通過測試。寫出來後我們覺得哪裡想改,再回頭改一下就好。」
而你仔細想想,這句話成立的前提,是什麼?就是「可執行規格」。
如果你手上沒有這種 Feature file,請問你到底怎麼跟 AI 說清楚你要什麼?
又要怎麼在完全不看程式碼的情況下,讓 AI 準確知道你想修改哪一段邏輯?
你試試看不用 Feature file,光要描述「某個功能想改」,你 prompt 不知道要下多少字,還不一定講得清楚,講完還要擔心 AI 誤會你。但如果你有幾十個 Scenario 已經列在 Feature file 裡,你只要打開對的情境,直接修改 Given / When / Then 就好了。
只要測試情境改了,AI 就知道該怎麼改程式碼,改到通過所有驗收為止。這就是可執行規格的威力。這也是為什麼我們說:可執行規格不只是規格,更是一種「黑箱測試」。
一份文件,兩種功能。它既能驅動 AI 去實作符合規格的程式,又能在實作完成後,自動驗證結果是否正確。而且這份可執行規格文件,不可能過時,因為它會和程式碼一起被維護,畢竟他是測試,這種文件又被稱之為「活文件 (Living Documentation)」。
不只是你(工程師)可以改 Scenario,
所有職能角色、所有 Stakeholder 都可以透過這份「可執行規格」,精準地把需求交給 AI。像是行銷想要新增活動、PM 想要取消某個優惠,都可以直接改規格,測試一跑,行為就變了。
總結:可執行規格的五大好處
最後,我們回頭來總結「可執行規格」到底在 AI 時代下,為我們帶來了哪些巨大的好處:
- 沒有技術細節,任何人都看得懂
不再只有工程師看得懂測試,連業務、PM、設計、老闆都能直接讀懂每一個系統行為的「情境 + 結果」。 - 促進跨部門需求溝通及協作
可執行規格並不是技術文件,而是所有 Stakeholder 都能參與維護的「活的規格書 (Living Document)」。不用來回溝通改需求,直接改 Feature file。 - 需求變更快速安全
想改某個行為?直接改對應的 Scenario 就好!當你跑測試時,整份系統的驗收規格會一次性告訴你、告訴 AI 哪些測試出問題,哪些已經正確實作。 - 測試步驟高度重用
先苦後甘,花點時間寫好測試步驟(Step Definitions),可以支援上百種情境規格。Scenario 越多,反而越划算。 - AI 全自動化開發的切入點
Feature file 就是未來 AI 開發的語言橋樑。人類只要懂得維護可執行規格,剩下的測試步驟和程式實作全部交給 AI。
朋友們,就是這個「可執行規格」的技術實現,讓你從「與 AI 協作」的低效率開發方式,晉升成「結果導向」的開發方式。
這個可執行規格不只是規格,還是份測試呢。不管 AI 開發的過程長什麼樣子,隨便啦,只要他結果對就好了啊,只要 AI 開發的結果通過這個「可執行規格」的測試,就代表他寫的程式碼是正確的啊。
因此啊,Code Review 時,我們首先要讀的是 AI 寫的測試步驟,讀完測試步驟之後確定測試寫對之後,其實你對 production code 的 review 就不必這麼歇斯底里了。
你看你同事的 Code 肯定也不是用肉眼去看他寫的業務邏輯是不是全對,一定是大致看看有沒有超出預期、看起來就明顯不合理的業務處理,順便確定沒有效能上的問題。
畢竟肉眼又不像是自動化測試,我們怎麼可能靠眼睛抓到所有錯誤,一定是靠測試確保程式無誤,如果在 AI 時代下你還不心力花在測試步驟上,而是花在 Code Review 上,效率也仍然低落。
好,你是否開始可以想像到了呢?軟體工程師不再需要花一堆時間與 AI 協作,而是將可執行規格書寫好,剩下的全部交給 AI 來幫你實現。
OK,這樣你知道下一篇文我要講什麼了嗎?
沒錯,接下來我要來講清楚,你到底要怎麼樣在訂定完可執行規格之後,讓 AI 幫你完整實作剩下的程式碼,不只是實作,連測試步驟也全部都交給 AI 實現,你一行程式碼都不用寫!
當你知道何謂「實例化需求」,也知道什麼叫「可執行規格」之後,最後一步就是要把所有拼圖拼起來——用測試驅動開發來命令 AI 做到全自動化開發吧!
如果想要在六個小時內立刻掌握 AI x BDD,該怎麼做?
要在六個小時內掌握 AI x BDD 全自動化開發的做法,只靠自己摸石頭前進是不可能的。
就算讀完了《BDD in Action》這本書,就算對於 BDD 的各個工程環節都有所掌握,也仍距離 AI 全自動化開發有一大距離。
如果真的想要讓 AI 能夠依照 BDD 的指示,精準且可靠地把每一步驟做好,有太多的細節需要留意:
- 該怎麼做實例化需求,寫到什麼程度才能保證 AI 看得懂?
- 看懂實例之後?用什麼測試架構,才能保證 AI 產出絕對與需求一致的測試?
- 測試架構的設計如何釋放 AI 的效率?AI Agent 把測試寫得越來越肥,效率越來越差了,該怎麼辦!
- 實例化需求的重用該怎麼做?規格上做「情境重用」,可是技術上該如何讓 AI 也懂得「情境重用」?
- AI 寫完 given / when / then 之後要做什麼?如何讓 AI 自己寫 code、自己試錯、自己修正,做到獨立作業?
- 就算 AI 已經能做到 BDD 獨立開發了,到底又要怎麼樣讓他不眠不休地連續工作好幾十個小時?做到「全自動化開發」?
這些全部都是智慧的結晶啊!每一個環節都需要花費超級大量時間研究,才能找出正確的方法。如果你不想花費半年時間來研究的話,那就直接上課吧!
《AI 時代的 1% 工程師:用「行為驅動開發 (BDD)」 實現百倍效率的 Vibe Coding 》是水球老師精心製作的一日工作坊課程,現正熱賣中。
如果要想要用 6 小時工作坊的時間,立刻速成學會如何用 BDD 來讓 AI 全自動化開發?那就上課吧!
實體場:https://www.accupass.com/event/2506110435103759406480
線上場:https://www.accupass.com/event/2506160524377577825710