bdd
SKILL.md
BDD — Behavior Driven Development
BDD 用結構化的自然語言(Gherkin)定義軟體行為,並用測試框架自動驗證。
檔案組織
- 依照功能分出不同 Context 資料夾
- steps 資料夾用來存放 Step definitions,因為同一 Context 很常共用 Step 所以每個 Context 建立一個檔案即可
- 如果有多個 Context 共用的 Step 也可以提取到 steps/shared.steps.ts 資料夾中定義 step
- 根據不同的測試框架可能還會有 supports 之類的資料夾
features/
├── [context1]/ ← 一個 Context 一個資料夾
│ ├── [feature1].feature
│ └── [feature2].feature
├── [context2]/
│ └── [feature3].feature
└── steps/ ← Step definitions 資料夾
├── [context1].steps.ts ← 一個 Context 一個檔案
└── [context2].steps.ts
.feature 變更管理
| 情境 | 處理方式 |
|---|---|
| 新增功能 | 新增 .feature 和 Scenario |
| 功能不變,加邊界情況 | 修改 .feature 中的 Scenario |
| 規格改了(字數限制等) | 修改 .feature 中的 Scenario |
| 功能整個砍掉 | 刪除 .feature + 告知對應 skill 清理程式碼 |
工作流程
1. 與使用者討論需求 → 釐清 Happy Path、Edge Cases、Boundary,撰寫 .feature
↓
2. 定義 feature 的 steps,撰寫 .steps.ts
↓
3. 實作功能
↓
4. 根據語言/平台建議測試工具
↓
5. 產生測試程式、執行測試
↓
6. [失敗] → 回報問題 → 呼叫其他 skill 修復 → 重新驗證
↓
7. [通過] → 回報完成 → 回到 1. 開始定義下一個需求
1. 產出 .feature 文件
由使用者撰寫,或由 Agent 協助使用者討論後產出。
Discovery — 探索需求
對每個功能,問三個問題:
- 正常路徑是什麼?(Happy Path)
- 異常路徑有哪些?(Edge Cases)
- 邊界條件?(Boundary)
Formulation — 撰寫 Gherkin Feature 檔案
基本結構
Feature: 功能名稱
身為 [角色]
我想要 [做什麼]
以便 [達成什麼目的]
Scenario: 場景名稱
Given [前提條件 / 初始狀態]
When [使用者的操作]
Then [預期的結果]
關鍵字
| 關鍵字 | 用途 | 重點 |
|---|---|---|
| Feature | 描述一個功能 | 一個 .feature 檔案一個 Feature |
| Scenario | 一個具體的使用場景 | 各 Scenario 完全獨立,互不影響 |
| Given | 前提條件 / 初始狀態 | 描述「邏輯狀態」,不是操作步驟 |
| When | 使用者的操作 | 觸發行為的動作 |
| Then | 預期的結果 | 可驗證的斷言 |
| And / But | 接續上一個關鍵字 | 讓語句更自然 |
進階語法
Background — 共用前提條件:
Background:
Given 我已登入
And 待辦列表中有以下項目:
| 項目 |
| 買牛奶 |
| 寫報告 |
Scenario Outline — 參數化測試:
Scenario Outline: 拒絕無效的待辦事項
When 我嘗試新增 "<輸入>"
Then 應該顯示錯誤訊息 "<錯誤>"
Examples:
| 輸入 | 錯誤 |
| | 不能為空 |
| aaaa...100 | 不能超過 100 字 |
Data Table — 嵌入結構化資料:
Given 待辦列表中有以下項目:
| 項目 | 狀態 |
| 買牛奶 | 未完成 |
| 寫報告 | 已完成 |
Tags — 標記和篩選:
@smoke
Scenario: 成功新增
@wip
Scenario: 拖曳排序(開發中)
npx cucumber-js --tags "@smoke"
npx cucumber-js --tags "not @wip"
撰寫原則
✅ Do
- 用業務語言,不用技術語言
# ✅ When 我新增一個待辦事項 "買牛奶" # ❌ When 我 dispatch ADD_TODO action with payload "買牛奶" - 每個 Scenario 獨立,有自己的 Given
- Scenario 標題描述意圖,不描述操作
# ✅ Scenario: 防止新增空白待辦事項 # ❌ Scenario: 輸入空字串按新增 - 一個 Scenario 只測一個行為
- Given 描述狀態,不描述操作步驟
❌ Don't
- 不要在 .feature 中寫 UI 細節(CSS selector 等)
- 不要窮舉所有邊界值(交給單元測試)
- 不要讓 Scenario 之間有隱含的順序依賴
- 不要寫太細碎的 Step
2. 建立 Step Definitions 骨架
將 .feature 拆解成可執行的 steps 程式碼骨架,實作細節交給對應的測試工具 skill,例如 playwright skill。
建立 features/steps/[context].steps.ts:
import { Given, When, Then } from '@cucumber/cucumber';
Given('我已登入', function() {
// TODO: 實作登入邏輯(呼叫對應的測試工具 skill)
});
When('我新增一個待辦事項 {string}', function(todo: string) {
// TODO: 實作新增待辦事項
});
Then('待辦列表應該包含 {string}', function(todo: string) {
// TODO: 實作斷言
});
3. 實作功能
正式開發功能
4. 選擇測試工具
根據專案的語言和平台,選擇適合的測試工具:
| 環境 | 工具 | 適用場景 |
|---|---|---|
| Node.js / JavaScript | cucumber-js | 基本 BDD |
| 網頁 E2E | playwright-bdd | 瀏覽器自動化 |
| API 測試 | PactumJS | HTTP API |
| React Native | detox | 行動裝置 E2E |
| Flutter | pickled_cucumber | Flutter E2E |
| Python | behave | Python BDD |
| Java | Cucumber JVM | Java BDD |
| .NET | SpecFlow | .NET BDD |
更多工具參考 Cucumber Related Tools
⚠️ AI 實作注意事項:防範只寫邏輯不寫 UI
BDD 的 .feature 寫作建議依照行為去描述功能,不含 UI 操作步驟和詳細的 UI 變化。
但由 AI Agent 實作時,若只要求 AI 讓 BDD 全部綠燈通過,AI 可能會只實作業務邏輯而不實作 UI!
因此,強烈建議針對網頁或 App 專案,指定使用具有 E2E (End-to-End) 測試能力的工具(如 playwright-bdd、detox 等)。
若專案未使用 E2E 測試工具,必要時仍可在 feature 中描述部分的 UI 操作與使用者會看到的結果,類似將 BDD 稍微偏向 E2E Test,藉此強迫 AI 確實將 UI 實作出來。
5. 生成測試、執行測試
根據不同測試工具會有不同,請參考專案架構和選擇的測試工具來產生測試程式,以 playwright-bdd 為例
# 根據 features 產生測試程式 (.features-gen)
npx bddgen
# 執行測試
npx playwright-bdd test
6. 分析失敗
當測試失敗時:
- 解讀失敗訊息 - 找出是哪個 Scenario、哪一行失敗
- 判斷問題類型:
.feature描述不清 → 回報使用者釐清- Step Definitions 缺少 → 建立骨架
- 實作程式碼錯誤 → 呼叫對應 skill 修復
- 無法修復 → 回報使用者告知問題與進度
7. 測試成功
告知使用者目前進度,若還有未完成的內容,繼續執行
Weekly Installs
1
Repository
cacaorick/skillsFirst Seen
9 days ago
Security Audits
Installed on
zencoder1
amp1
cline1
openclaw1
opencode1
cursor1