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 — 探索需求

對每個功能,問三個問題:

  1. 正常路徑是什麼?(Happy Path)
  2. 異常路徑有哪些?(Edge Cases)
  3. 邊界條件?(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
  1. 用業務語言,不用技術語言
    # ✅ When 我新增一個待辦事項 "買牛奶"
    # ❌ When 我 dispatch ADD_TODO action with payload "買牛奶"
    
  2. 每個 Scenario 獨立,有自己的 Given
  3. Scenario 標題描述意圖,不描述操作
    # ✅ Scenario: 防止新增空白待辦事項
    # ❌ Scenario: 輸入空字串按新增
    
  4. 一個 Scenario 只測一個行為
  5. Given 描述狀態,不描述操作步驟
❌ Don't
  1. 不要在 .feature 中寫 UI 細節(CSS selector 等)
  2. 不要窮舉所有邊界值(交給單元測試)
  3. 不要讓 Scenario 之間有隱含的順序依賴
  4. 不要寫太細碎的 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-bdddetox 等)。 若專案未使用 E2E 測試工具,必要時仍可在 feature 中描述部分的 UI 操作與使用者會看到的結果,類似將 BDD 稍微偏向 E2E Test,藉此強迫 AI 確實將 UI 實作出來。


5. 生成測試、執行測試

根據不同測試工具會有不同,請參考專案架構和選擇的測試工具來產生測試程式,以 playwright-bdd 為例

# 根據 features 產生測試程式 (.features-gen)
npx bddgen

# 執行測試
npx playwright-bdd test

6. 分析失敗

當測試失敗時:

  1. 解讀失敗訊息 - 找出是哪個 Scenario、哪一行失敗
  2. 判斷問題類型
    • .feature 描述不清 → 回報使用者釐清
    • Step Definitions 缺少 → 建立骨架
    • 實作程式碼錯誤 → 呼叫對應 skill 修復
    • 無法修復 → 回報使用者告知問題與進度

7. 測試成功

告知使用者目前進度,若還有未完成的內容,繼續執行

Weekly Installs
1
First Seen
9 days ago
Installed on
zencoder1
amp1
cline1
openclaw1
opencode1
cursor1