Initial commit
This commit is contained in:
11
.claude-plugin/plugin.json
Normal file
11
.claude-plugin/plugin.json
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"name": "test-first-tdd",
|
||||||
|
"description": "Structured Test-First TDD: Plan-driven approach with comprehensive documentation and verification",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"author": {
|
||||||
|
"name": "cash"
|
||||||
|
},
|
||||||
|
"commands": [
|
||||||
|
"./commands"
|
||||||
|
]
|
||||||
|
}
|
||||||
3
README.md
Normal file
3
README.md
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
# test-first-tdd
|
||||||
|
|
||||||
|
Structured Test-First TDD: Plan-driven approach with comprehensive documentation and verification
|
||||||
187
commands/tf-green.md
Normal file
187
commands/tf-green.md
Normal file
@@ -0,0 +1,187 @@
|
|||||||
|
---
|
||||||
|
description: 執行TDD的Green階段。實作功能讓失敗的測試通過。
|
||||||
|
---
|
||||||
|
|
||||||
|
# TDD Green階段(實作功能)
|
||||||
|
|
||||||
|
執行TDD的Green階段,實作最小功能讓測試通過。
|
||||||
|
|
||||||
|
**【功能名】**:{{feature_name}}
|
||||||
|
|
||||||
|
## 事前準備
|
||||||
|
|
||||||
|
請確認:
|
||||||
|
- Red 階段的測試已建立
|
||||||
|
- 測試執行後會失敗
|
||||||
|
- memo.md 已記錄 Red 階段進度
|
||||||
|
|
||||||
|
## Green 階段目標
|
||||||
|
|
||||||
|
**實作最小功能讓測試通過。**
|
||||||
|
|
||||||
|
**重要原則:**
|
||||||
|
- 只要能讓測試通過就好
|
||||||
|
- 程式碼簡潔優先,不用考慮完美
|
||||||
|
- 複雜的最佳化留到 Refactor 階段
|
||||||
|
- 先求能動,再求完美
|
||||||
|
|
||||||
|
## 實作原則
|
||||||
|
|
||||||
|
### 1. 最小實作優先
|
||||||
|
```javascript
|
||||||
|
// ❌ 不要一開始就寫複雜的實作
|
||||||
|
function calculate(a, b) {
|
||||||
|
// 複雜的驗證和錯誤處理
|
||||||
|
// 效能最佳化
|
||||||
|
// 各種邊界條件處理
|
||||||
|
...
|
||||||
|
}
|
||||||
|
|
||||||
|
// ✅ 先寫最簡單能通過測試的程式碼
|
||||||
|
function calculate(a, b) {
|
||||||
|
return a + b;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 階段性實作
|
||||||
|
- 先讓一個測試通過
|
||||||
|
- 再讓下一個測試通過
|
||||||
|
- 逐步增加功能
|
||||||
|
|
||||||
|
### 3. 容許暫時的解決方案
|
||||||
|
- 可以使用硬編碼
|
||||||
|
- 可以先忽略邊界條件
|
||||||
|
- 重構階段再改善
|
||||||
|
|
||||||
|
## 實作程式碼註解要求
|
||||||
|
|
||||||
|
### 函式層級註解
|
||||||
|
```javascript
|
||||||
|
/**
|
||||||
|
* 【功能說明】:此函式的功能
|
||||||
|
* 【實作方針】:為什麼這樣實作
|
||||||
|
* 【對應測試】:為了通過哪個測試
|
||||||
|
*
|
||||||
|
* @param {type} paramName - 參數說明
|
||||||
|
* @returns {type} - 回傳值說明
|
||||||
|
*/
|
||||||
|
function functionName(paramName) {
|
||||||
|
// 實作內容
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 處理區塊註解
|
||||||
|
```javascript
|
||||||
|
function processData(input) {
|
||||||
|
// 【輸入驗證】:檢查輸入是否有效
|
||||||
|
if (!input) {
|
||||||
|
throw new Error('輸入不可為空');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 【主要處理】:核心功能實作
|
||||||
|
const result = doSomething(input);
|
||||||
|
|
||||||
|
// 【回傳結果】:回傳處理結果
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 變數註解
|
||||||
|
```javascript
|
||||||
|
// 【初始化】:設定初始值
|
||||||
|
const initialValue = 0;
|
||||||
|
|
||||||
|
// 【計數器】:追蹤處理數量
|
||||||
|
let count = 0;
|
||||||
|
```
|
||||||
|
|
||||||
|
## 實作步驟
|
||||||
|
|
||||||
|
1. **執行測試確認失敗**:
|
||||||
|
```bash
|
||||||
|
npm test
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **實作最小功能**:
|
||||||
|
- 只實作讓測試通過所需的程式碼
|
||||||
|
- 加入繁體中文註解
|
||||||
|
- 保持程式碼簡單
|
||||||
|
|
||||||
|
3. **再次執行測試**:
|
||||||
|
- 確認測試通過
|
||||||
|
- 如果失敗,修正後重試
|
||||||
|
|
||||||
|
4. **更新 memo.md**:
|
||||||
|
- 記錄實作內容
|
||||||
|
- 標註下一步改善項目
|
||||||
|
|
||||||
|
## memo.md 更新格式
|
||||||
|
|
||||||
|
在 memo.md 中加入 Green 階段記錄:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
## Green 階段(實作功能)
|
||||||
|
|
||||||
|
### 日期
|
||||||
|
{當前日期時間}
|
||||||
|
|
||||||
|
### 實作內容
|
||||||
|
{簡述實作了什麼功能}
|
||||||
|
|
||||||
|
### 實作檔案位置
|
||||||
|
{實作檔案路徑}
|
||||||
|
|
||||||
|
### 測試結果
|
||||||
|
- ✅ 測試 1:通過
|
||||||
|
- ✅ 測試 2:通過
|
||||||
|
...
|
||||||
|
|
||||||
|
### 待改善項目
|
||||||
|
{列出應該在 Refactor 階段改善的地方}
|
||||||
|
|
||||||
|
### 下一步
|
||||||
|
進入 Refactor 階段,改善程式碼品質。
|
||||||
|
```
|
||||||
|
|
||||||
|
## 常見的最小實作策略
|
||||||
|
|
||||||
|
### 策略 1:硬編碼
|
||||||
|
```javascript
|
||||||
|
// 先用固定值通過測試
|
||||||
|
function getGreeting() {
|
||||||
|
return "Hello, World!";
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 策略 2:假實作
|
||||||
|
```javascript
|
||||||
|
// 先回傳符合格式的假資料
|
||||||
|
function fetchData() {
|
||||||
|
return { status: 'success', data: [] };
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 策略 3:簡單邏輯
|
||||||
|
```javascript
|
||||||
|
// 用最簡單的邏輯實作
|
||||||
|
function isEven(num) {
|
||||||
|
return num % 2 === 0;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 品質檢查
|
||||||
|
|
||||||
|
完成後請確認:
|
||||||
|
- ✅ 所有測試都通過
|
||||||
|
- ✅ 實作程式碼有繁體中文註解
|
||||||
|
- ✅ 程式碼簡單易懂
|
||||||
|
- ✅ 已記錄到 memo.md
|
||||||
|
- ✅ 已標註待改善項目
|
||||||
|
|
||||||
|
## 下一步
|
||||||
|
|
||||||
|
Green 階段完成後,執行:
|
||||||
|
```
|
||||||
|
/tf-refactor
|
||||||
|
```
|
||||||
|
開始改善程式碼品質(Refactor 階段)。
|
||||||
170
commands/tf-red.md
Normal file
170
commands/tf-red.md
Normal file
@@ -0,0 +1,170 @@
|
|||||||
|
---
|
||||||
|
description: 執行TDD的Red階段。建立會失敗的測試,明確定義應實作的功能。
|
||||||
|
---
|
||||||
|
|
||||||
|
# TDD Red階段(建立失敗的測試)
|
||||||
|
|
||||||
|
執行TDD的Red階段,建立會失敗的測試。
|
||||||
|
|
||||||
|
**【功能名】**:{{feature_name}}
|
||||||
|
|
||||||
|
## 事前準備
|
||||||
|
|
||||||
|
請確認以下文件已存在:
|
||||||
|
```
|
||||||
|
docs/tdd/{feature_name}/requirements.md
|
||||||
|
docs/tdd/{feature_name}/testcases.md
|
||||||
|
```
|
||||||
|
|
||||||
|
## Red 階段目標
|
||||||
|
|
||||||
|
建立會失敗的測試,明確定義功能的行為。
|
||||||
|
|
||||||
|
**重要原則:**
|
||||||
|
- 測試必須是會失敗的(因為功能尚未實作)
|
||||||
|
- 測試要清楚定義預期的行為
|
||||||
|
- 測試要容易理解和維護
|
||||||
|
|
||||||
|
## 測試程式碼要求
|
||||||
|
|
||||||
|
### 1. 測試檔案結構
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// 測試檔案:__tests__/{feature_name}.test.js
|
||||||
|
|
||||||
|
describe('{feature_name}', () => {
|
||||||
|
// 【測試群組說明】:此群組測試的功能範圍
|
||||||
|
|
||||||
|
test('測試案例名稱', () => {
|
||||||
|
// 【測試目的】:說明此測試要驗證什麼
|
||||||
|
// 【測試內容】:具體測試的處理
|
||||||
|
// 【預期行為】:正常情況下的結果
|
||||||
|
|
||||||
|
// Given - 準備測試資料
|
||||||
|
// 【測試資料準備】:說明為何準備這些資料
|
||||||
|
const input = testData;
|
||||||
|
|
||||||
|
// When - 執行測試
|
||||||
|
// 【執行功能】:呼叫要測試的功能
|
||||||
|
const result = functionToTest(input);
|
||||||
|
|
||||||
|
// Then - 驗證結果
|
||||||
|
// 【驗證結果】:確認符合預期
|
||||||
|
expect(result).toBe(expectedValue);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 繁體中文註解規範
|
||||||
|
|
||||||
|
每個測試必須包含:
|
||||||
|
|
||||||
|
**測試開始的註解:**
|
||||||
|
```javascript
|
||||||
|
// 【測試目的】:此測試要確認什麼功能
|
||||||
|
// 【測試內容】:具體要測試的處理
|
||||||
|
// 【預期行為】:正常情況下應該得到的結果
|
||||||
|
```
|
||||||
|
|
||||||
|
**Given(準備)階段:**
|
||||||
|
```javascript
|
||||||
|
// 【測試資料準備】:說明準備這些資料的原因
|
||||||
|
// 【初始條件】:測試執行前的狀態
|
||||||
|
```
|
||||||
|
|
||||||
|
**When(執行)階段:**
|
||||||
|
```javascript
|
||||||
|
// 【執行功能】:說明呼叫哪個功能
|
||||||
|
// 【處理內容】:這個功能做什麼處理
|
||||||
|
```
|
||||||
|
|
||||||
|
**Then(驗證)階段:**
|
||||||
|
```javascript
|
||||||
|
// 【驗證結果】:要確認什麼結果
|
||||||
|
// 【預期值】:為什麼這是正確的結果
|
||||||
|
```
|
||||||
|
|
||||||
|
**每個 expect 的註解:**
|
||||||
|
```javascript
|
||||||
|
expect(result.value).toBe(10); // 【確認】:數值正確為 10
|
||||||
|
expect(result.status).toBe('success'); // 【確認】:狀態為成功
|
||||||
|
```
|
||||||
|
|
||||||
|
## 實作步驟
|
||||||
|
|
||||||
|
1. **選擇測試案例**:
|
||||||
|
- 從 testcases.md 選擇要實作的測試
|
||||||
|
- 建議從最簡單的正常系統測試開始
|
||||||
|
|
||||||
|
2. **建立測試檔案**:
|
||||||
|
- 在適當位置建立測試檔案
|
||||||
|
- 設定測試框架和相關 import
|
||||||
|
|
||||||
|
3. **撰寫測試程式碼**:
|
||||||
|
- 按照 Given-When-Then 結構
|
||||||
|
- 加入完整的繁體中文註解
|
||||||
|
- 確保測試會失敗(功能尚未實作)
|
||||||
|
|
||||||
|
4. **執行測試**:
|
||||||
|
- 確認測試會失敗
|
||||||
|
- 失敗訊息要清楚易懂
|
||||||
|
|
||||||
|
5. **記錄到 memo**:
|
||||||
|
- 更新 docs/tdd/{feature_name}/memo.md
|
||||||
|
- 記錄 Red 階段的進度
|
||||||
|
|
||||||
|
## memo.md 格式
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
# {feature_name} TDD 開發記錄
|
||||||
|
|
||||||
|
## Red 階段(建立失敗的測試)
|
||||||
|
|
||||||
|
### 日期
|
||||||
|
{當前日期時間}
|
||||||
|
|
||||||
|
### 已建立的測試
|
||||||
|
- 測試案例 1:{測試名稱}
|
||||||
|
- 測試案例 2:{測試名稱}
|
||||||
|
...
|
||||||
|
|
||||||
|
### 測試檔案位置
|
||||||
|
{測試檔案路徑}
|
||||||
|
|
||||||
|
### 預期的失敗
|
||||||
|
{說明為什麼這些測試會失敗}
|
||||||
|
|
||||||
|
### 下一步
|
||||||
|
進入 Green 階段,實作功能讓測試通過。
|
||||||
|
```
|
||||||
|
|
||||||
|
## 測試執行命令
|
||||||
|
|
||||||
|
根據使用的測試框架:
|
||||||
|
|
||||||
|
**Jest/Vitest:**
|
||||||
|
```bash
|
||||||
|
npm test
|
||||||
|
# 或
|
||||||
|
npm test -- {test_file_name}
|
||||||
|
```
|
||||||
|
|
||||||
|
**其他框架:**
|
||||||
|
請根據專案設定執行測試命令。
|
||||||
|
|
||||||
|
## 品質檢查
|
||||||
|
|
||||||
|
完成後請確認:
|
||||||
|
- ✅ 測試會失敗(因為功能未實作)
|
||||||
|
- ✅ 失敗訊息清楚易懂
|
||||||
|
- ✅ 測試有完整的繁體中文註解
|
||||||
|
- ✅ 測試結構清晰(Given-When-Then)
|
||||||
|
- ✅ 已記錄到 memo.md
|
||||||
|
|
||||||
|
## 下一步
|
||||||
|
|
||||||
|
Red 階段完成後,執行:
|
||||||
|
```
|
||||||
|
/tf-green
|
||||||
|
```
|
||||||
|
開始實作功能讓測試通過(Green 階段)。
|
||||||
276
commands/tf-refactor.md
Normal file
276
commands/tf-refactor.md
Normal file
@@ -0,0 +1,276 @@
|
|||||||
|
---
|
||||||
|
description: 執行TDD的Refactor階段。在測試通過後,改善程式碼品質。
|
||||||
|
---
|
||||||
|
|
||||||
|
# TDD Refactor階段(程式碼重構)
|
||||||
|
|
||||||
|
執行TDD的Refactor階段,改善程式碼品質。
|
||||||
|
|
||||||
|
**【功能名】**:{{feature_name}}
|
||||||
|
|
||||||
|
## 事前準備
|
||||||
|
|
||||||
|
請確認:
|
||||||
|
- 所有測試都通過
|
||||||
|
- Green 階段的實作已完成
|
||||||
|
- memo.md 已記錄待改善項目
|
||||||
|
|
||||||
|
## Refactor 階段目標
|
||||||
|
|
||||||
|
**在保持測試通過的前提下,改善程式碼品質。**
|
||||||
|
|
||||||
|
**重要原則:**
|
||||||
|
- 測試必須持續通過
|
||||||
|
- 不改變功能行為
|
||||||
|
- 小步改善,頻繁測試
|
||||||
|
- 改善後測試,測試失敗立即回復
|
||||||
|
|
||||||
|
## 改善的重點
|
||||||
|
|
||||||
|
### 1. 提高可讀性
|
||||||
|
- 改善變數和函式命名
|
||||||
|
- 增加或改善註解
|
||||||
|
- 簡化複雜的邏輯
|
||||||
|
|
||||||
|
### 2. 消除重複(DRY原則)
|
||||||
|
```javascript
|
||||||
|
// ❌ 重複的程式碼
|
||||||
|
function processA(data) {
|
||||||
|
if (!data) throw new Error('無效資料');
|
||||||
|
return data.value * 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
function processB(data) {
|
||||||
|
if (!data) throw new Error('無效資料');
|
||||||
|
return data.value * 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ✅ 提取共通邏輯
|
||||||
|
function validateData(data) {
|
||||||
|
if (!data) throw new Error('無效資料');
|
||||||
|
}
|
||||||
|
|
||||||
|
function processA(data) {
|
||||||
|
validateData(data);
|
||||||
|
return data.value * 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
function processB(data) {
|
||||||
|
validateData(data);
|
||||||
|
return data.value * 3;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. 改善程式結構
|
||||||
|
- 單一職責原則(每個函式只做一件事)
|
||||||
|
- 提取魔術數字為常數
|
||||||
|
- 簡化條件判斷
|
||||||
|
|
||||||
|
### 4. 改善註解品質
|
||||||
|
```javascript
|
||||||
|
/**
|
||||||
|
* 【功能說明】:計算折扣後的價格
|
||||||
|
* 【改善說明】:提取折扣計算邏輯,提高可讀性
|
||||||
|
* 【使用情境】:結帳時計算最終價格
|
||||||
|
*
|
||||||
|
* @param {number} price - 原始價格
|
||||||
|
* @param {number} discount - 折扣百分比(0-100)
|
||||||
|
* @returns {number} - 折扣後價格
|
||||||
|
*/
|
||||||
|
function calculateDiscountedPrice(price, discount) {
|
||||||
|
// 【參數驗證】:確保價格和折扣都是有效數值
|
||||||
|
if (price < 0 || discount < 0 || discount > 100) {
|
||||||
|
throw new Error('無效的價格或折扣');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 【折扣計算】:套用折扣百分比
|
||||||
|
const discountAmount = price * (discount / 100);
|
||||||
|
|
||||||
|
// 【最終價格】:原價減去折扣金額
|
||||||
|
return price - discountAmount;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 重構步驟
|
||||||
|
|
||||||
|
### 步驟 1:執行測試確認全部通過
|
||||||
|
```bash
|
||||||
|
npm test
|
||||||
|
```
|
||||||
|
|
||||||
|
### 步驟 2:識別改善點
|
||||||
|
根據 memo.md 中記錄的待改善項目:
|
||||||
|
- 重複的程式碼
|
||||||
|
- 不清楚的命名
|
||||||
|
- 複雜的邏輯
|
||||||
|
- 缺少的註解
|
||||||
|
|
||||||
|
### 步驟 3:小步改善
|
||||||
|
每次只改善一個地方:
|
||||||
|
1. 改善一個項目
|
||||||
|
2. 執行測試
|
||||||
|
3. 測試通過,繼續下一個
|
||||||
|
4. 測試失敗,立即回復
|
||||||
|
|
||||||
|
### 步驟 4:更新 memo.md
|
||||||
|
記錄重構內容
|
||||||
|
|
||||||
|
## 常見重構技巧
|
||||||
|
|
||||||
|
### 技巧 1:提取函式
|
||||||
|
```javascript
|
||||||
|
// Before
|
||||||
|
function processOrder(order) {
|
||||||
|
// 驗證訂單
|
||||||
|
if (!order.items || order.items.length === 0) {
|
||||||
|
throw new Error('訂單沒有商品');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 計算總價
|
||||||
|
let total = 0;
|
||||||
|
for (const item of order.items) {
|
||||||
|
total += item.price * item.quantity;
|
||||||
|
}
|
||||||
|
|
||||||
|
return total;
|
||||||
|
}
|
||||||
|
|
||||||
|
// After
|
||||||
|
function processOrder(order) {
|
||||||
|
validateOrder(order);
|
||||||
|
return calculateTotal(order.items);
|
||||||
|
}
|
||||||
|
|
||||||
|
function validateOrder(order) {
|
||||||
|
// 【訂單驗證】:確保訂單包含商品
|
||||||
|
if (!order.items || order.items.length === 0) {
|
||||||
|
throw new Error('訂單沒有商品');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function calculateTotal(items) {
|
||||||
|
// 【總價計算】:計算所有商品的總價
|
||||||
|
let total = 0;
|
||||||
|
for (const item of items) {
|
||||||
|
total += item.price * item.quantity;
|
||||||
|
}
|
||||||
|
return total;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 技巧 2:提取常數
|
||||||
|
```javascript
|
||||||
|
// Before
|
||||||
|
function calculateShipping(weight) {
|
||||||
|
if (weight > 1000) {
|
||||||
|
return 100;
|
||||||
|
}
|
||||||
|
return 50;
|
||||||
|
}
|
||||||
|
|
||||||
|
// After
|
||||||
|
// 【運費常數】:定義不同重量級別的運費
|
||||||
|
const SHIPPING_COST = {
|
||||||
|
STANDARD: 50,
|
||||||
|
HEAVY: 100,
|
||||||
|
};
|
||||||
|
|
||||||
|
// 【重量門檻】:超過此重量視為重貨
|
||||||
|
const HEAVY_WEIGHT_THRESHOLD = 1000;
|
||||||
|
|
||||||
|
function calculateShipping(weight) {
|
||||||
|
// 【運費計算】:根據重量決定運費
|
||||||
|
if (weight > HEAVY_WEIGHT_THRESHOLD) {
|
||||||
|
return SHIPPING_COST.HEAVY;
|
||||||
|
}
|
||||||
|
return SHIPPING_COST.STANDARD;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 技巧 3:簡化條件
|
||||||
|
```javascript
|
||||||
|
// Before
|
||||||
|
function canPurchase(user, product) {
|
||||||
|
if (user.age >= 18) {
|
||||||
|
if (user.balance >= product.price) {
|
||||||
|
if (product.stock > 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// After
|
||||||
|
function canPurchase(user, product) {
|
||||||
|
// 【購買條件檢查】:驗證使用者和商品狀態
|
||||||
|
const isAdult = user.age >= 18;
|
||||||
|
const hasEnoughBalance = user.balance >= product.price;
|
||||||
|
const isInStock = product.stock > 0;
|
||||||
|
|
||||||
|
return isAdult && hasEnoughBalance && isInStock;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## memo.md 更新格式
|
||||||
|
|
||||||
|
在 memo.md 中加入 Refactor 階段記錄:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
## Refactor 階段(程式碼重構)
|
||||||
|
|
||||||
|
### 日期
|
||||||
|
{當前日期時間}
|
||||||
|
|
||||||
|
### 改善內容
|
||||||
|
1. {改善項目 1}
|
||||||
|
- 改善前:{描述}
|
||||||
|
- 改善後:{描述}
|
||||||
|
- 原因:{為什麼要這樣改善}
|
||||||
|
|
||||||
|
2. {改善項目 2}
|
||||||
|
...
|
||||||
|
|
||||||
|
### 測試結果
|
||||||
|
✅ 所有測試持續通過
|
||||||
|
|
||||||
|
### 程式碼品質評估
|
||||||
|
- 可讀性:{評估}
|
||||||
|
- 維護性:{評估}
|
||||||
|
- 效能:{評估}
|
||||||
|
|
||||||
|
### 下一步
|
||||||
|
進入完整性驗證階段。
|
||||||
|
```
|
||||||
|
|
||||||
|
## 品質檢查
|
||||||
|
|
||||||
|
完成後請確認:
|
||||||
|
- ✅ 所有測試都通過
|
||||||
|
- ✅ 程式碼更容易理解
|
||||||
|
- ✅ 減少了重複
|
||||||
|
- ✅ 註解更完整清楚
|
||||||
|
- ✅ 已記錄改善內容到 memo.md
|
||||||
|
|
||||||
|
## 注意事項
|
||||||
|
|
||||||
|
**禁止的行為:**
|
||||||
|
- ❌ 改變功能行為
|
||||||
|
- ❌ 新增功能
|
||||||
|
- ❌ 一次改太多
|
||||||
|
- ❌ 不執行測試就繼續改
|
||||||
|
|
||||||
|
**允許的行為:**
|
||||||
|
- ✅ 改善命名
|
||||||
|
- ✅ 提取函式
|
||||||
|
- ✅ 提取常數
|
||||||
|
- ✅ 增加註解
|
||||||
|
- ✅ 簡化邏輯
|
||||||
|
|
||||||
|
## 下一步
|
||||||
|
|
||||||
|
Refactor 階段完成後,執行:
|
||||||
|
```
|
||||||
|
/tf-verify
|
||||||
|
```
|
||||||
|
驗證開發完整性。
|
||||||
93
commands/tf-requirements.md
Normal file
93
commands/tf-requirements.md
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
---
|
||||||
|
description: 進行TDD開發的需求整理。明確化功能需求,為測試驅動開發做準備。
|
||||||
|
---
|
||||||
|
|
||||||
|
# TDD需求定義・功能規格的整理
|
||||||
|
|
||||||
|
開始TDD開發。請針對以下功能整理需求:
|
||||||
|
|
||||||
|
**【功能名】**:{{feature_name}}
|
||||||
|
|
||||||
|
## 使用說明
|
||||||
|
|
||||||
|
請提供功能描述,我會幫您整理成結構化的需求文件。
|
||||||
|
|
||||||
|
**提供資訊範例:**
|
||||||
|
- 功能的目的和解決的問題
|
||||||
|
- 預期的輸入和輸出
|
||||||
|
- 使用情境和範例
|
||||||
|
- 需要注意的限制條件
|
||||||
|
|
||||||
|
## TDD用需求整理格式
|
||||||
|
|
||||||
|
### 1. 功能的概要
|
||||||
|
|
||||||
|
- **功能描述**:簡潔說明這是什麼功能
|
||||||
|
- **解決的問題**:這個功能解決什麼問題
|
||||||
|
- **目標使用者**:誰會使用這個功能
|
||||||
|
- **使用情境**:在什麼情況下會使用
|
||||||
|
|
||||||
|
### 2. 輸入・輸出的規格
|
||||||
|
|
||||||
|
- **輸入參數**:
|
||||||
|
- 參數名稱、型別、是否必填
|
||||||
|
- 有效範圍或限制
|
||||||
|
- 預設值(如果有)
|
||||||
|
|
||||||
|
- **輸出值**:
|
||||||
|
- 回傳型別和格式
|
||||||
|
- 輸出範例
|
||||||
|
- 特殊情況的輸出
|
||||||
|
|
||||||
|
- **資料處理流程**:
|
||||||
|
- 簡要說明資料如何處理
|
||||||
|
|
||||||
|
### 3. 限制條件
|
||||||
|
|
||||||
|
- **效能需求**:
|
||||||
|
- 回應時間、處理量等要求
|
||||||
|
|
||||||
|
- **技術限制**:
|
||||||
|
- 使用的語言、框架
|
||||||
|
- 相容性要求
|
||||||
|
|
||||||
|
- **資料限制**:
|
||||||
|
- 資料大小限制
|
||||||
|
- 格式要求
|
||||||
|
|
||||||
|
### 4. 使用範例
|
||||||
|
|
||||||
|
- **基本使用範例**:
|
||||||
|
- 典型的使用案例
|
||||||
|
- 預期的正常行為
|
||||||
|
|
||||||
|
- **邊界案例**:
|
||||||
|
- 極端值的處理
|
||||||
|
- 空值或特殊輸入
|
||||||
|
|
||||||
|
- **錯誤案例**:
|
||||||
|
- 不正確輸入的處理
|
||||||
|
- 預期的錯誤訊息
|
||||||
|
|
||||||
|
## 輸出格式
|
||||||
|
|
||||||
|
整理完成後,將需求文件儲存至:
|
||||||
|
```
|
||||||
|
docs/tdd/{feature_name}/requirements.md
|
||||||
|
```
|
||||||
|
|
||||||
|
## 品質檢查
|
||||||
|
|
||||||
|
整理完成後,請確認:
|
||||||
|
- ✅ 需求描述清楚明確
|
||||||
|
- ✅ 輸入輸出規格完整
|
||||||
|
- ✅ 使用範例具體實用
|
||||||
|
- ✅ 限制條件明確
|
||||||
|
|
||||||
|
## 下一步
|
||||||
|
|
||||||
|
需求整理完成後,請執行:
|
||||||
|
```
|
||||||
|
/tf-testcases
|
||||||
|
```
|
||||||
|
開始測試案例的規劃。
|
||||||
116
commands/tf-testcases.md
Normal file
116
commands/tf-testcases.md
Normal file
@@ -0,0 +1,116 @@
|
|||||||
|
---
|
||||||
|
description: 進行TDD開發的測試案例規劃。根據需求定義規劃完整的測試案例。
|
||||||
|
---
|
||||||
|
|
||||||
|
# TDD測試案例的規劃
|
||||||
|
|
||||||
|
根據需求文件,規劃涵蓋完整的測試案例。
|
||||||
|
|
||||||
|
**【功能名】**:{{feature_name}}
|
||||||
|
|
||||||
|
## 事前準備
|
||||||
|
|
||||||
|
請先確認需求文件已存在:
|
||||||
|
```
|
||||||
|
docs/tdd/{feature_name}/requirements.md
|
||||||
|
```
|
||||||
|
|
||||||
|
## 測試案例分類
|
||||||
|
|
||||||
|
### 1. 正常系統測試案例(基本功能)
|
||||||
|
|
||||||
|
記載格式:
|
||||||
|
- **測試名稱**:清楚描述測試目的
|
||||||
|
- **測試內容**:要驗證什麼功能
|
||||||
|
- **輸入值**:具體的測試資料
|
||||||
|
- **預期結果**:應該得到什麼輸出
|
||||||
|
- **測試目的**:為什麼需要這個測試
|
||||||
|
|
||||||
|
### 2. 異常系統測試案例(錯誤處理)
|
||||||
|
|
||||||
|
記載格式:
|
||||||
|
- **測試名稱**:描述錯誤情境
|
||||||
|
- **測試內容**:要驗證的錯誤處理
|
||||||
|
- **輸入值**:不正確或異常的資料
|
||||||
|
- **預期結果**:預期的錯誤訊息或例外
|
||||||
|
- **測試目的**:確保適當的錯誤處理
|
||||||
|
|
||||||
|
### 3. 邊界值測試案例(極端情況)
|
||||||
|
|
||||||
|
記載格式:
|
||||||
|
- **測試名稱**:描述邊界條件
|
||||||
|
- **測試內容**:要驗證的邊界行為
|
||||||
|
- **輸入值**:最小值、最大值、空值等
|
||||||
|
- **預期結果**:邊界情況的正確處理
|
||||||
|
- **測試目的**:確保極端情況的穩定性
|
||||||
|
|
||||||
|
## 技術選擇
|
||||||
|
|
||||||
|
請指定測試使用的技術:
|
||||||
|
- **程式語言**:如 JavaScript、TypeScript、Python 等
|
||||||
|
- **測試框架**:如 Jest、Vitest、pytest 等
|
||||||
|
- **測試類型**:單元測試、整合測試等
|
||||||
|
|
||||||
|
## 測試程式碼註解要求
|
||||||
|
|
||||||
|
測試程式碼必須包含繁體中文註解:
|
||||||
|
|
||||||
|
### 測試開始的註解
|
||||||
|
```javascript
|
||||||
|
describe('功能名稱', () => {
|
||||||
|
test('測試案例名稱', () => {
|
||||||
|
// 【測試目的】:說明此測試要驗證什麼
|
||||||
|
// 【測試內容】:具體測試的處理
|
||||||
|
// 【預期行為】:正常情況下的結果
|
||||||
|
});
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### Given-When-Then 註解
|
||||||
|
```javascript
|
||||||
|
// 【測試資料準備 Given】:準備測試所需的資料
|
||||||
|
const input = testData;
|
||||||
|
|
||||||
|
// 【執行測試 When】:呼叫要測試的功能
|
||||||
|
const result = functionToTest(input);
|
||||||
|
|
||||||
|
// 【驗證結果 Then】:確認結果符合預期
|
||||||
|
expect(result).toBe(expectedValue);
|
||||||
|
```
|
||||||
|
|
||||||
|
### 驗證點的註解
|
||||||
|
```javascript
|
||||||
|
expect(result.value).toBe(10); // 【確認】:數值正確為 10
|
||||||
|
expect(result.status).toBe('success'); // 【確認】:狀態為成功
|
||||||
|
expect(result.errors).toHaveLength(0); // 【確認】:沒有錯誤
|
||||||
|
```
|
||||||
|
|
||||||
|
## 輸出格式
|
||||||
|
|
||||||
|
規劃完成後,將測試案例清單儲存至:
|
||||||
|
```
|
||||||
|
docs/tdd/{feature_name}/testcases.md
|
||||||
|
```
|
||||||
|
|
||||||
|
測試案例文件應包含:
|
||||||
|
1. 測試案例總覽(數量統計)
|
||||||
|
2. 正常系統測試案例清單
|
||||||
|
3. 異常系統測試案例清單
|
||||||
|
4. 邊界值測試案例清單
|
||||||
|
5. 技術選擇說明
|
||||||
|
|
||||||
|
## 品質檢查
|
||||||
|
|
||||||
|
規劃完成後,請確認:
|
||||||
|
- ✅ 涵蓋所有需求項目
|
||||||
|
- ✅ 測試案例分類完整
|
||||||
|
- ✅ 每個測試案例都有明確的預期結果
|
||||||
|
- ✅ 技術選擇明確
|
||||||
|
|
||||||
|
## 下一步
|
||||||
|
|
||||||
|
測試案例規劃完成後,請執行:
|
||||||
|
```
|
||||||
|
/tf-red
|
||||||
|
```
|
||||||
|
開始建立失敗的測試(Red 階段)。
|
||||||
219
commands/tf-verify.md
Normal file
219
commands/tf-verify.md
Normal file
@@ -0,0 +1,219 @@
|
|||||||
|
---
|
||||||
|
description: 驗證TDD開發的完整性。確認所有測試案例都已實作且通過。
|
||||||
|
---
|
||||||
|
|
||||||
|
# TDD 開發完整性驗證
|
||||||
|
|
||||||
|
驗證TDD開發是否完整,確保所有規劃的測試案例都已實作並通過。
|
||||||
|
|
||||||
|
**【功能名】**:{{feature_name}}
|
||||||
|
|
||||||
|
## 驗證目的
|
||||||
|
|
||||||
|
確認:
|
||||||
|
1. 所有規劃的測試案例都已實作
|
||||||
|
2. 所有測試都通過
|
||||||
|
3. 功能開發完整
|
||||||
|
|
||||||
|
## 驗證檔案
|
||||||
|
|
||||||
|
需要檢查的文件:
|
||||||
|
```
|
||||||
|
docs/tdd/{feature_name}/requirements.md
|
||||||
|
docs/tdd/{feature_name}/testcases.md
|
||||||
|
docs/tdd/{feature_name}/memo.md
|
||||||
|
```
|
||||||
|
|
||||||
|
需要檢查的程式碼:
|
||||||
|
- 測試檔案(如 `__tests__/*.test.js`)
|
||||||
|
- 實作檔案(如 `src/*.js`)
|
||||||
|
|
||||||
|
## 驗證步驟
|
||||||
|
|
||||||
|
### 1. 執行所有測試
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm test
|
||||||
|
```
|
||||||
|
|
||||||
|
確認:
|
||||||
|
- ✅ 所有測試都通過
|
||||||
|
- ✅ 沒有被跳過的測試
|
||||||
|
- ✅ 測試覆蓋率合理
|
||||||
|
|
||||||
|
### 2. 比對測試案例清單
|
||||||
|
|
||||||
|
從 `testcases.md` 讀取規劃的測試案例,檢查:
|
||||||
|
- 規劃了幾個測試案例
|
||||||
|
- 實際實作了幾個
|
||||||
|
- 哪些測試案例尚未實作
|
||||||
|
|
||||||
|
### 3. 檢查需求覆蓋
|
||||||
|
|
||||||
|
從 `requirements.md` 檢查:
|
||||||
|
- 所有輸入參數都有測試
|
||||||
|
- 所有輸出格式都有驗證
|
||||||
|
- 錯誤處理都有測試
|
||||||
|
- 邊界條件都有涵蓋
|
||||||
|
|
||||||
|
## 驗證報告格式
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
# {feature_name} TDD 開發完整性驗證報告
|
||||||
|
|
||||||
|
## 測試執行結果
|
||||||
|
- 測試總數:{數量}
|
||||||
|
- 通過:{數量}
|
||||||
|
- 失敗:{數量}
|
||||||
|
- 跳過:{數量}
|
||||||
|
- 成功率:{百分比}%
|
||||||
|
|
||||||
|
## 測試案例實作狀況
|
||||||
|
|
||||||
|
### 規劃的測試案例
|
||||||
|
- 正常系統:{數量} 個
|
||||||
|
- 異常系統:{數量} 個
|
||||||
|
- 邊界值:{數量} 個
|
||||||
|
- 總計:{數量} 個
|
||||||
|
|
||||||
|
### 已實作的測試案例
|
||||||
|
- 正常系統:{數量} 個
|
||||||
|
- 異常系統:{數量} 個
|
||||||
|
- 邊界值:{數量} 個
|
||||||
|
- 總計:{數量} 個
|
||||||
|
|
||||||
|
### 實作率
|
||||||
|
- 整體實作率:{百分比}%
|
||||||
|
|
||||||
|
## 需求覆蓋狀況
|
||||||
|
|
||||||
|
### 已覆蓋的需求
|
||||||
|
- {需求項目 1}:✅ 已測試
|
||||||
|
- {需求項目 2}:✅ 已測試
|
||||||
|
...
|
||||||
|
|
||||||
|
### 未覆蓋的需求
|
||||||
|
- {需求項目 X}:❌ 尚未測試
|
||||||
|
...
|
||||||
|
|
||||||
|
## 完整性判定
|
||||||
|
|
||||||
|
{✅ 完整 / ⚠️ 不完整}
|
||||||
|
|
||||||
|
### 判定理由
|
||||||
|
{說明為什麼判定為完整或不完整}
|
||||||
|
|
||||||
|
## 建議
|
||||||
|
|
||||||
|
{如果不完整,列出建議的改善項目}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 更新 memo.md
|
||||||
|
|
||||||
|
在 memo.md 中加入驗證結果:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
## 完整性驗證
|
||||||
|
|
||||||
|
### 日期
|
||||||
|
{當前日期時間}
|
||||||
|
|
||||||
|
### 驗證結果
|
||||||
|
{完整 / 不完整}
|
||||||
|
|
||||||
|
### 測試統計
|
||||||
|
- 測試總數:{數量}
|
||||||
|
- 成功率:{百分比}%
|
||||||
|
- 實作率:{百分比}%
|
||||||
|
|
||||||
|
### 需求覆蓋
|
||||||
|
- 已覆蓋:{數量} 項
|
||||||
|
- 未覆蓋:{數量} 項
|
||||||
|
|
||||||
|
### 結論
|
||||||
|
{總結開發成果}
|
||||||
|
|
||||||
|
### 後續建議
|
||||||
|
{如有需要,列出後續改善項目}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 判定基準
|
||||||
|
|
||||||
|
### ✅ 完整(開發完成)
|
||||||
|
|
||||||
|
滿足所有條件:
|
||||||
|
- 所有測試都通過(100%)
|
||||||
|
- 實作率達 100%(或合理說明未實作的原因)
|
||||||
|
- 需求覆蓋率達 100%
|
||||||
|
- 程式碼品質良好
|
||||||
|
|
||||||
|
### ⚠️ 不完整(需要繼續開發)
|
||||||
|
|
||||||
|
有以下任一情況:
|
||||||
|
- 有測試失敗
|
||||||
|
- 重要測試案例未實作
|
||||||
|
- 重要需求未覆蓋
|
||||||
|
- 程式碼品質有明顯問題
|
||||||
|
|
||||||
|
## 驗證完成後的行動
|
||||||
|
|
||||||
|
### 如果驗證通過(完整)
|
||||||
|
|
||||||
|
1. 在 memo.md 中標記為完成
|
||||||
|
2. 整理開發記錄
|
||||||
|
3. 結束此功能的 TDD 開發
|
||||||
|
|
||||||
|
### 如果驗證未通過(不完整)
|
||||||
|
|
||||||
|
1. 在 memo.md 中記錄缺失項目
|
||||||
|
2. 返回相應階段補充:
|
||||||
|
- 缺測試案例 → 返回 `/tf-red`
|
||||||
|
- 測試未通過 → 返回 `/tf-green`
|
||||||
|
- 程式碼品質 → 返回 `/tf-refactor`
|
||||||
|
|
||||||
|
## 輸出範例
|
||||||
|
|
||||||
|
### 完整的情況
|
||||||
|
|
||||||
|
```
|
||||||
|
✅ TDD 開發完整性驗證:通過
|
||||||
|
|
||||||
|
📊 測試統計
|
||||||
|
- 測試總數:15 個
|
||||||
|
- 全部通過
|
||||||
|
- 成功率:100%
|
||||||
|
- 實作率:100%
|
||||||
|
|
||||||
|
📋 需求覆蓋
|
||||||
|
- 全部需求項目都已測試
|
||||||
|
- 覆蓋率:100%
|
||||||
|
|
||||||
|
🎉 功能開發完成!
|
||||||
|
```
|
||||||
|
|
||||||
|
### 不完整的情況
|
||||||
|
|
||||||
|
```
|
||||||
|
⚠️ TDD 開發完整性驗證:未通過
|
||||||
|
|
||||||
|
📊 測試統計
|
||||||
|
- 測試總數:12 個
|
||||||
|
- 通過:10 個
|
||||||
|
- 失敗:2 個
|
||||||
|
- 成功率:83.3%
|
||||||
|
- 實作率:80%
|
||||||
|
|
||||||
|
❌ 未實作的測試案例
|
||||||
|
1. 邊界值測試:空陣列的處理
|
||||||
|
2. 錯誤測試:無效輸入的錯誤訊息
|
||||||
|
3. 邊界值測試:最大值超過限制
|
||||||
|
|
||||||
|
📝 建議
|
||||||
|
請返回 Red 階段,補充缺失的測試案例。
|
||||||
|
```
|
||||||
|
|
||||||
|
## 下一步
|
||||||
|
|
||||||
|
驗證完成後:
|
||||||
|
- 如果完整:功能開發結束,可以開始下一個功能
|
||||||
|
- 如果不完整:根據驗證報告返回相應階段繼續開發
|
||||||
65
plugin.lock.json
Normal file
65
plugin.lock.json
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
{
|
||||||
|
"$schema": "internal://schemas/plugin.lock.v1.json",
|
||||||
|
"pluginId": "gh:cashwu/claude-code-tdd-marketplace:plugins/test-first-tdd",
|
||||||
|
"normalized": {
|
||||||
|
"repo": null,
|
||||||
|
"ref": "refs/tags/v20251128.0",
|
||||||
|
"commit": "4b8ab40c08dcb7190032bf55dcc4f56ba1305a53",
|
||||||
|
"treeHash": "f32a8190dcbddcfdfa2176eff12689a71ebfb407228e54979013936a94175608",
|
||||||
|
"generatedAt": "2025-11-28T10:14:30.440840Z",
|
||||||
|
"toolVersion": "publish_plugins.py@0.2.0"
|
||||||
|
},
|
||||||
|
"origin": {
|
||||||
|
"remote": "git@github.com:zhongweili/42plugin-data.git",
|
||||||
|
"branch": "master",
|
||||||
|
"commit": "aa1497ed0949fd50e99e70d6324a29c5b34f9390",
|
||||||
|
"repoRoot": "/Users/zhongweili/projects/openmind/42plugin-data"
|
||||||
|
},
|
||||||
|
"manifest": {
|
||||||
|
"name": "test-first-tdd",
|
||||||
|
"description": "Structured Test-First TDD: Plan-driven approach with comprehensive documentation and verification",
|
||||||
|
"version": "1.0.0"
|
||||||
|
},
|
||||||
|
"content": {
|
||||||
|
"files": [
|
||||||
|
{
|
||||||
|
"path": "README.md",
|
||||||
|
"sha256": "563b2d154faab8567504b23b38fa16480ca39d6797989128cf87cda6f208b62b"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": ".claude-plugin/plugin.json",
|
||||||
|
"sha256": "b717dc06711ef1f3da361e3bc36b1e1a899b5b5508c8c9d1d3076f457a740327"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "commands/tf-testcases.md",
|
||||||
|
"sha256": "7bcbcde60f93e25e6cb48a15d8a95d47d1c84e5ed3f073f6eaa679e88cf42ccd"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "commands/tf-red.md",
|
||||||
|
"sha256": "7527e8fa12317839a7dee941c896a0cc4365d282f2206e810930af574416aa2d"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "commands/tf-green.md",
|
||||||
|
"sha256": "64c6e294c233122fb6be5ce8f2669835a33eb3223765e651c3fa4b244268ac31"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "commands/tf-refactor.md",
|
||||||
|
"sha256": "f305d6e21153f40230cb44cf7beb310ee243f6096597b7dc0f75d20935944b2d"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "commands/tf-verify.md",
|
||||||
|
"sha256": "eda7ab003662d71a79d27d84b570beed2567892e72cd4b2ebb3df3d6969e4d6e"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "commands/tf-requirements.md",
|
||||||
|
"sha256": "67943dd71df39b6d06c630ebb5bf01c45baa5c74533d5a2ea53f0098e14bad5e"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"dirSha256": "f32a8190dcbddcfdfa2176eff12689a71ebfb407228e54979013936a94175608"
|
||||||
|
},
|
||||||
|
"security": {
|
||||||
|
"scannedAt": null,
|
||||||
|
"scannerVersion": null,
|
||||||
|
"flags": []
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user