O

test-driven-development

作者 obra

一套嚴謹的 test-driven-development 工作流程,要求先寫測試、強制執行 Red-Green-Refactor 循環,並在實際專案中避免常見的測試反模式。

Stars0
收藏0
評論0
分類测试自動化
安裝指令
npx skills add https://github.com/obra/superpowers --skill test-driven-development
總覽

概觀

這個技能在做什麼

test-driven-development 技能將嚴格的 Test-Driven Development(TDD)工作流程具體化:你必須先寫會失敗的測試,再撰寫任何 production code,並遵守有紀律的 Red-Green-Refactor 循環。

這不是鬆散的「之後再來補測試」建議,而是一組明確的硬性規則:

  • 沒有先失敗的測試,就不能寫 production code
  • 一定要確認測試是因為正確的原因而失敗
  • 只寫剛好足以讓測試通過的最小程式碼
  • 在所有測試都綠燈後再重構

此外,它也會連結到專門的 testing-anti-patterns 指南,協助你避免脆弱、誤導的測試寫法。

適用對象

如果你符合以下情況,就很適合使用 test-driven-development 技能:

  • 想要在開發功能、修 bug、做重構時,都有可靠流程的 開發者
  • 想將 TDD 做為團隊標準,並需要明確規則讓每個人遵循的 團隊
  • 想要強化、統一自動化測試習慣的 教練或技術主管

這個技能對 JavaScriptTypeScript 專案特別實用,但其原則適用於任何語言與測試框架。

這個技能要解決的問題

這個技能專門用來處理日常開發中常見的幾個痛點:

  • 先寫程式,測試晚點再說,甚至根本沒寫
  • 不確定測試是否真的驗證了預期行為
  • 因為測試薄弱或缺失,而害怕重構
  • 過度或錯誤使用 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-Refactor
  • testing-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 中的範例主要以 JavaScriptTypeScript 為主,但你可以在任何技術棧中套用同樣的 TDD 規則:

  • JavaScript/TypeScript 專案(例如使用 Jest、Vitest 或 Mocha):

    • 一律在修改 production 檔案前,先新增或調整測試(例如 *.test.ts*.spec.ts
    • 對每一個應用程式程式碼變更,都用 Red-Green-Refactor 循環包起來
  • 對其他語言(例如 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:列出撰寫測試時常見的錯誤做法,提醒你避免踩雷

在日常開發時,把這兩個檔案當作你工作流程的參考文件。

評分與評論

尚無評分
分享你的評論
登入後即可為這項技能評分並留言。
G
0/10000
最新評論
儲存中...