test-driven-development
作者 obra一套嚴謹的 test-driven-development 工作流程,要求先寫測試、強制執行 Red-Green-Refactor 循環,並在實際專案中避免常見的測試反模式。
概觀
這個技能在做什麼
test-driven-development 技能將嚴格的 Test-Driven Development(TDD)工作流程具體化:你必須先寫會失敗的測試,再撰寫任何 production code,並遵守有紀律的 Red-Green-Refactor 循環。
這不是鬆散的「之後再來補測試」建議,而是一組明確的硬性規則:
- 沒有先失敗的測試,就不能寫 production code
- 一定要確認測試是因為正確的原因而失敗
- 只寫剛好足以讓測試通過的最小程式碼
- 在所有測試都綠燈後再重構
此外,它也會連結到專門的 testing-anti-patterns 指南,協助你避免脆弱、誤導的測試寫法。
適用對象
如果你符合以下情況,就很適合使用 test-driven-development 技能:
- 想要在開發功能、修 bug、做重構時,都有可靠流程的 開發者
- 想將 TDD 做為團隊標準,並需要明確規則讓每個人遵循的 團隊
- 想要強化、統一自動化測試習慣的 教練或技術主管
這個技能對 JavaScript 和 TypeScript 專案特別實用,但其原則適用於任何語言與測試框架。
這個技能要解決的問題
這個技能專門用來處理日常開發中常見的幾個痛點:
- 先寫程式,測試晚點再說,甚至根本沒寫
- 不確定測試是否真的驗證了預期行為
- 因為測試薄弱或缺失,而害怕重構
- 過度或錯誤使用 mock,只是在測「假行為」,而不是實際行為
透過遵循 test-driven-development 工作流程,你可以:
- 從失敗的測試獲得 快速回饋
- 保留清楚的 預期行為紀錄
- 讓 重構更安全,因為行為已由測試鎖定
- 避免只驗證 mock 或實作細節的脆弱測試
何時該用(以及何時不必用)
上游的技能說明明確建議在以下情境使用 TDD:
- 新功能
- Bug 修復
- 重構工作
- 任何行為上的變更
同時也提到一些應與真人搭配討論的例外,例如:
- 一次性拋棄的 prototype
- 產生出來的程式碼
- 組態檔(configuration files)
如果你只是「隨便探索一下」或快速 hack 一個之後會丟掉的 spike,這種嚴格的 test-driven-development 技能可能比你需要的還重。但在正式上線的功能上,這套流程預期應該是 預設工作流程,而不是可有可無的額外選項。
使用方式
安裝
要從 obra/superpowers repository 安裝 test-driven-development 技能,請執行:
npx skills add https://github.com/obra/superpowers --skill test-driven-development
這會把 test-driven-development 的技能定義與相關檔案拉進你的 Agent Skills 環境。安裝完成後,你可以打開技能的檔案,查看詳細規則與測試反模式範例。
這個技能會用到的關鍵檔案包括:
SKILL.md– 核心 TDD 規則,包括 Iron Law 以及 Red-Green-Refactortesting-anti-patterns.md– 專門說明測試中哪些事情 不要 做的指南
核心原則:Iron Law
這個技能的核心是原始專案中所稱的 Iron Law:
NO PRODUCTION CODE WITHOUT A FAILING TEST FIRST
實務上的含意是:
- 如果你先寫了 production code 才寫測試,你必須 把那段程式碼刪掉重來
- 你 不能 把它留著當「參考」,或是一邊寫測試一邊改它
- 你 不能 在依照測試重新實作時偷偷偷看被刪掉的程式碼
這條硬性規則確保每一行 production code 都是因實際測試需求而產生。
逐步 TDD 工作流程
安裝好 test-driven-development 技能後,就可以把它當作預設的開發流程來使用:
1. 寫一個會失敗的測試(RED)
- 先釐清一個 單一行為(新功能、bug 修復,或重構後預期結果)
- 寫一個 新的測試,清楚表達預期行為
- 執行測試,並 確認這個新測試確實失敗
在 RED 這個步驟,你還沒完成前必須:
- 看到測試失敗
- 確認它是因為 正確的原因 失敗(對的 assertion、對的錯誤類型)
如果失敗的原因不對(例如測試在 setup 就爆掉,或拋出意料之外的錯誤),就先修測試,重新執行,直到它以有意義的方式失敗為止。
2. 加上最小程式碼讓測試通過(GREEN)
- 只實作 剛好足夠 讓失敗的測試通過的最簡單程式碼
- 避免過早設計、抽象化或額外邏輯
- 執行整個測試套件,確保新測試變成 綠燈,而且既有測試仍全部通過
技能的說明刻意強調這一步範圍要窄:你的目標不是「一次做完整個功能」,而是 滿足眼前這個測試。
3. 安全地重構(REFACTOR)
在所有測試都綠燈之後:
- 清理 production code:移除重複、簡化邏輯、調整命名讓程式更易懂
- 清理測試程式:提升可讀性、必要時抽出共用 helper
- 持續頻繁地跑測試,確認行為沒有變化
這樣可以在維持行為不變的情況下,靠測試保護,持續改善設計。
4. 重複整個循環
對每一個小行為或邊界情境:
- 再加一個測試(RED)
- 讓它通過(GREEN)
- 視需要重構(REFACTOR)
test-driven-development 技能的角色,就是把你牢牢鎖在這個循環裡,讓你很難替自己找藉口跳過任何一步。
與你的技術棧整合
Repository 中的範例主要以 JavaScript 和 TypeScript 為主,但你可以在任何技術棧中套用同樣的 TDD 規則:
-
對 JavaScript/TypeScript 專案(例如使用 Jest、Vitest 或 Mocha):
- 一律在修改 production 檔案前,先新增或調整測試(例如
*.test.ts或*.spec.ts) - 對每一個應用程式程式碼變更,都用 Red-Green-Refactor 循環包起來
- 一律在修改 production 檔案前,先新增或調整測試(例如
-
對其他語言(例如 Python、Java、Go、C#):
- 將相同步驟對應到你使用的測試框架(pytest、JUnit、Go test、xUnit 等)
- 那條嚴格規則「no production code without a failing test」同樣適用
這個技能本身不會把你綁在特定框架上;它編碼的是 工作流程規則,不是 library 依賴。
使用 testing anti-patterns 指南
內含的 testing-anti-patterns.md 檔案是 test-driven-development 技能的配套指南。每當你:
- 在撰寫或修改測試
- 在加入 mocks 或 stubs
- 想要在 production class 或 module 裡加「只給測試用」的 hooks
都很適合載入或參考這份文件。
指南中的核心原則包括:
- 不要測 mock 的行為 – 測試應該驗證真實行為,而不是只是驗證 mock 存在
- 不要為了測試而在 production classes 裡加專用方法 – 保持 production API 乾淨
- 不要在不清楚依賴關係時就亂 mock – 過度 mock 只會帶來虛假的信心
這些反模式範例使用 TypeScript 風格的測試來展示「壞寫法 vs 好寫法」,你可以再依自己的測試框架調整。
依團隊情境調整工作流程
安裝之後,你可以在不破壞核心精神的前提下,把 test-driven-development 技能中的規則微調成符合你們團隊實況的版本:
- 先對齊哪些類型的變更 必須 嚴格遵守 TDD(例如所有 production modules、domain logic、關鍵流程)
- 一起定義少數的例外情境(例如快速 spike 或產生的程式碼),但要把它們明確列出
- 把 Iron Law 納入 code review 清單:
- 「這個變更對應的失敗測試在哪裡?」
- 「這個測試是先寫的嗎?」
這有助於把這個技能變成 團隊標準,而不只是個人習慣。
常見問題(FAQ)
test-driven-development 技能跟特定測試框架綁在一起嗎?
不會。test-driven-development 技能定義的是 工作流程與規則,而不是特定的測試框架。Repository 裡的範例偏向 JavaScript 和 TypeScript,但你可以在任何語言中套用同樣的 Red-Green-Refactor 循環。
我真的必須刪掉在沒有測試的情況下寫好的程式碼嗎?
依照 SKILL.md 中的 Iron Law,答案是是的。如果你在沒有先寫會失敗的測試的情況下就寫了 production code,規則就是 把那些程式碼刪掉,從測試開始重來。背後的理念是杜絕把測試當成事後補上的想法。
什麼情況下這個技能不太適合?
上游的說明列出幾個可能的例外情境,例如一次性 prototype、產生出來的程式碼或組態檔。對於生命週期很短的實驗性 spikes,嚴格的 test-driven-development 確實可能太重。但對於準備要上線的功能、bug 修復與重構,這個技能就是預設建議的做法。
這個技能如何幫助除錯和重構?
在修 bug 或重構時:
- 一開始先寫一個會失敗的測試,重現 bug 或描述你想要的預期行為
- 接著調整程式碼,直到測試通過
- 最後再放心地進行重構,因為測試會幫你守住行為
這能讓除錯流程更有系統,也讓重構變得更安全。
沒有任何測試的 legacy code 也能用這個技能嗎?
可以,但你很可能需要 漸進式 套用:
- 每當你要動到一塊 legacy 區域時,先加一個測試,捕捉目前或預期的行為
- 如果你要改變行為,先看它失敗,然後讓它通過
- 用 Red-Green-Refactor 循環,逐步讓那一區塊進入可測試、可保護的狀態
久而久之,會有越來越多 legacy code 被測試保護住。
安裝完成後應該從哪裡開始?
在執行安裝指令之後,可以先打開:
SKILL.md:裡面有核心的 test-driven-development 規則,以及 Red-Green-Refactor 的說明testing-anti-patterns.md:列出撰寫測試時常見的錯誤做法,提醒你避免踩雷
在日常開發時,把這兩個檔案當作你工作流程的參考文件。
