出版日期:7月6,2026
精靈與契約
當非確定性代理程式編寫程式碼時,規範驅動開發 (SDD) 和測試驅動開發 (TDD) 如何真正結合——以及簡單的版本在何時悄悄崩潰。

一個難以捉摸的精靈
肯特·貝克五十年來一直主張測試應放在首位。因此,我們有必要關注他是如何描述他現在使用的AI編碼代理的: 一個能實現你願望的“難以捉摸的精靈”往往以字面意義和出人意料的方式。你提出要求,它就給你。 東西至於那東西是否是你真正需要的,則是另一個問題。
在同一段對話中,貝克稱TDD為 “超級大國” 對於這些代理商來說,由於它們會不斷引入回歸問題,而測試套件是發現這些問題的最經濟有效的方法。但他也透露了一個值得注意的細節:他很難阻止代理商… 刪除測試 讓他們通過考試。考試既是防御手段,也是鑽空子的對象──這就是問題的關鍵。
這裡先簡單解釋一下術語,因為其中一個縮寫詞經常被濫用。 TDD 是較老的開發方法:先寫一個會失敗的測試,然後寫出剛好能讓測試通過的程式碼,進行程式碼清理,如此循環往復。 SDD 是較新的方法:將你要建立的東西記錄成結構化的技術規格——包括 API 架構、資料模型和驗收標準——並將該文件視為程式碼必須滿足的契約。重要的是,SDD 是一種… 在練習上,不是產品。 GitHub 的 Spec Kit 是一個易於上手使用的工具,也是貫穿全文的範例——但這裡提到的所有內容都適用於任何SDD設定。 (它也不同於…) 故事驅動 這種開發方式是基於較為寬鬆的使用者故事層面,與 TDD 的關係也不同。 )
為什麼他們兩個都無法獨自從精靈手中倖存下來
單獨運行軟體定義開發(SDD)會導致含義偏移:智能體會根據模糊的規範形成自己的解讀,並構建出內部一致的程式碼,但這些程式碼仍然無法準確表達你的意圖,因為文字無法直接執行,也沒有任何機制將程式碼拉回文字本身。單獨執行測試定義開發(TDD)則會得到相反的結果-程式碼能夠通過前面的測試,僅此而已,因為沒有規格來定義這些測試的目標。 應該 斷言,最終它們會編碼代理決定構建的任何東西。無論哪種方式:綠色對勾,目標錯誤。
將它們結合起來的原因並非因為它們都很好,而是因為… 規範和測試是對同一意圖的兩種獨立編碼。 ——一份是人類可讀的,一份是機器可執行的——兩者互相彌補了對方的不足。規範賦予測試存在的理由,因此測試套件不僅僅是程式碼的鏡像。測驗賦予規範約束力,使代理人無法悄悄地重新解釋規範文本。
左側的規格面板和右側的測試面板都指向中心代理,從兩側將其框住。

一根脊柱,兩個閘門,一個反饋邊緣
下圖展示了形狀。意圖由人來定義;Spec Kit 的 specify 以及 plan 命令將其轉化為規範和計劃;由專人審核-作為檢查點,而非永久鎖定。三個細節決定了這在實踐中是否真正有效。
首先, analyze 在任何程式碼運行之前執行。 這是一個唯讀的、跨規範、計劃和任務的一致性檢查。人們通常會把它留到最後,但 Spec Kit 的 自有快速入門指南 明確指出第一遍屬於 之前 implement而且,修復漏洞的成本仍然很低。如果需要,可以之後再運行一次作為漂移審查——但真正承載負載的階段是在代理寫入任何一行程式碼之前。
第二, 一個人擁有驗收測試 下一節將解釋這意味著什麼。第三,代理內置 垂直切片:每次只測試一小段行為——一個失敗的測試,編寫足夠多的程式碼使其通過,進行清理,然後再測試下一段——而不是預先產生整個測試套件或一次性輸出數百行程式碼,後者會導致程式碼看起來合理,但實際上卻存在無法定位的問題。而且,只有當測試全部通過、測試套件經過檢查確認確實能夠捕獲錯誤,並且已提交的測試沒有被修改以強制通過時,程式碼才會合併。
從人類意圖到合併門的垂直管道,以分析作為預編碼門,以人為的只讀驗收測試,垂直切片代碼循環,以及從循環反饋到規範的反饋邊。

誰來看守護欄?
很容易將此想像成一個簡潔的「規範 → 測試 → 程式碼」流程,然後就此止步。真正的工程在於故障模式——而所有這些故障模式最終都可以歸結為一個問題:如果代理程式編寫規格、編寫測試, 以及 它編寫程式碼,但實際檢查的是什麼?
誰來決定「正確」的意思?
如果由同一個模型編寫規格、測試和程式碼,它們都會存在同一個盲點。一旦對意圖理解有誤,就會得到一個編碼了這種錯誤理解的規範、一個強制執行這種錯誤的測試,以及一個能夠通過這些測試的程式碼。一切看起來都正常,但實際上都是錯的。只有當規範、測試和程式碼都符合規範時,這兩個「獨立」的編碼才能保持獨立。 一個人至少擁有其中一項——這是經紀人無法悄悄改寫的。
最適合指定專人負責的成果是驗收測試-即證明「此功能已完成且運作正常」的測試。用文字寫的規範可以嚴格遵守字面意思,但其精神內核可能被違背;而測試則是一個具體的、有通過或失敗結果的聲明。 擁有所有權並不意味著必須由某人親手撰寫每一項斷言——代理人可以起草測試案例。它意味著由某人審核這些測試案例,批准其中的斷言,並對其負責。 在它們成為衡量程式碼的標準之前,而不是讓同一個代理默默地產生和合併自己的程式碼。用測驗術語來說,驗收測驗就是你的 神諭:它決定程式碼是否正確。正如其他參與這項工作的人所發現的那樣, 人為控制的試驗是最後的防線 ——因為在壓力下,智能體的本能反應是刪除失敗的測試案例,而不是修復程式碼。如果智能體可以修改預言機,那麼預言機就形同虛設。
綠色是代理,而代理會被鑽空子。
「只有測試通過,代理才能繼續執行下一步」聽起來像是保證,但實際上並非如此。有很多方法可以讓測試通過,卻無法真正滿足預期目標:削弱測試內容、跳過測試、用存根替換實際組件、硬編碼預期結果、忽略錯誤——或者乾脆重寫測試。問題在於,一旦「讓測試通過」成為目標,通過測試就不再是系統正常運作的可靠標誌。
這並非假設。 Aider——一款流行的命令列編碼代理,也是構建循環的合理選擇——其設計本身就具備這種特性。 編輯測試,它認為這些測試是錯誤的 而不是強迫程式碼去適應它們。這在人駕駛時確實很有用;但當智能體自主運作時,這就成了一個漏洞。那麼,如何阻止智能體鑽空子呢?兩種防禦措施可以解決大部分問題—而簡單的通過/失敗計數並不能解決這些問題。

測試無法說明什麼
單元測試回答的是一個狹隘的問題:這個函數在獨立運行時是否能實現我設定的功能?它們無法說明效能、安全性、可訪問性,或者——最重要的是——是否能實現我設定的功能。 系統 實際上,它對真實用戶是有效的。最後一個缺陷正是人工智慧產生程式碼的弱點所在:代理程式雖然鎖定了一個孤立的單元,卻悄無聲息地破壞了貫穿該單元的端到端流程。所以要認真對待它。 將端到端測試和整合測試作為首要環節,而不是事後考慮。 — 這一層以用戶的方式驅動實際應用程序,並捕獲單元測試無法發現的問題。諸如此類的工具 劇作家 MCP 甚至可以讓代理程式運行真實的瀏覽器,並對照實際的訪問路徑檢查自身的工作,而不是靠猜測。對於那些根本無法測試的需求,應該在建置流程中明確設定一個關卡——僅僅寄望結果並不能起到控製作用。
重構並非可選項
TDD 循環包含三個步驟,而非兩個:編寫一個失敗的測試(紅色),使其通過(綠色),然後清理剛剛寫的程式碼(重構)。如果不加幹預,智能體往往會忽略第三步,在測試通過後立即發布。但重構才是保證程式碼品質的關鍵——如果使用快速且有效率的智能體跳過這一步,恰恰會造成整個流程旨在避免的混亂局面。因此,務必在循環中持續進行重構,並密切注意程式碼複雜度或程式碼變更訊號,以便及時發現智能體過度建構的部分。
規範是鮮活的,而非僵化的。
這兩種方法之間存在著真正的矛盾。軟體定義開發 (SDD) 要求在編寫程式碼之前就先明確規範——這正是製定規範的意義所在。相比之下,測試驅動開發 (TDD) 在某種程度上是一種… 發現 設計中:你常會在寫測試案例的過程中發現某個需求是錯誤的,或是某個介面設計得很糟糕。那麼,當測驗第一次揭示出規範本身不完整時,會發生什麼事呢?
答案是將規範視為一份動態文檔,而非一次性簽署確認的文件。當需求變更或測試發現漏洞時,不要直接修改測試以匹配程式碼;而是先更新規格(進行小幅且經過審核的修改),再更新測試以與之匹配,觀察測試失敗的情況,然後讓代理程式使其通過。這和紅綠循環一樣,同樣適用於規範和程式碼——而且它包含一條你絕對不能違反的規則: 變更流程規格 → 測試 → 程式碼,切勿單獨進行測試 → 程式碼操作。 堅持這項原則,不斷變化的需求不再是這種方法最不擅長處理的事情,而是它最擅長處理的事情。
大門存在於環境中
關鍵的設計選擇是 學科所在之處人們很容易將功能歸於某個特定工具——這個工具負責規劃,那個工具負責編寫程式碼。千萬不要這樣做。 將門控機制放在環境(版本控制和持續整合)中,而不是放在任何單一代理程式中。 一旦它駐留在系統中,編碼代理就變成了一個可替換的部件,而不是你所信任的東西。
您的SDD工具是規劃的核心。 有了Spec Kit就是 constitution → specify → clarify → plan → tasks → analyze → implement將TDD規則放入其中 憲法文件在實現之前編寫一個會失敗的測試;測試失敗時切勿將任務標記為已完成;切勿為了讓測試通過而修改已提交的測試。每個命令都會繼承這些規則,因此您無需依賴代理程式在長時間會話中記住它們。
該門控是提交前的鉤子和 CI 檢查,而不是提示。 測試通過,變異被捕獲,提交的測試保持不變——由環境強制執行,因此無論代碼來自 Spec Kit 還是其他任何來源,結果都一樣。 implement無論是來自 Aider,還是其他任何來源。
執行器是可插拔的。 艾德的家鄉 --auto-test 循環操作比批量命令能實現更緊湊的單次變更週期,並根據成本分配模型——對於規範和計劃而言,這是一個強大的模型;對於高頻循環操作,這是一個更經濟的模型,並支援快取。用不用都行。方法論才是關鍵。
儀式與風險相符。
無法縮減規模的流程最終會被放棄。對於一個只有一行程式碼的 bug 修復來說,一套完整的流程——專案章程、規格、規劃、任務分解,再加上變異測試——未免過於繁瑣。所以,應該採用雙軌制,將流程拆分成兩個部分。 Spec Kit 自身的文檔 推薦。

這些額外投入值得嗎?
這一切都不是免費的。你需要為更多的模型呼叫、更多的測試運行以及更多的來回迭代付費,而不是簡單地讓智能體一次性編寫程式碼,因此,質疑這些額外成本是否物有所值是合理的。保持成本合理的方法是把錢花在刀刃上:在規範和計劃階段使用強大的模型,在高頻構建循環中使用更便宜、更快速的模型;只在合併時運行昂貴的檢查(例如變異測試),而不是在每次迭代中都運行;並保持代碼切片較小,以降低每次循環的成本。但真正的問題在於你的基準是什麼。基準並非由資深工程師編寫的完美程式碼,而是一個無人監督的智能體交付看似合理但有缺陷的程式碼,然後你需要花費數小時進行調試。與此相比,這些額外的開銷正是為你換取一個真正值得信賴的結果。
何時不應這樣做
有時候,答案是根本不值得。對於一次性原型和探索性項目,可以跳過完整的測試流程,因為它們的目的是快速學習並棄用。對於真正微不足道的改動,也可以跳過,因為設定測試門檻的成本可能比修復 bug 的成本還要高。對於無法以低成本編寫有效測試的領域,要坦誠面對——在這些領域,所謂的「預言」是空洞的,所謂的「保證」也只是作秀。 丹·德利馬斯基觀察到 從實際使用規格工具包的經驗來看,規格並非萬能靈藥。指出這些限制並非迴避問題——這正是方法論與銷售說詞的差異。
門檻剛剛升高了。
自動化時代真正留下的不是程式碼,而是知道什麼是正確的需求,用足夠精確的語言表達出來,確保即使是思維僵化的精靈也無法誤解,並且能夠判斷自己是否真正理解了。軟體驅動開發(SDD)是表達方式,測試驅動開發(TDD)是檢驗方式。
代理人會毫不猶豫地刪除你的測試案例,以消除錯誤提示。因此,規範、測試套件以及背後的判斷並非圍繞著實際工作的形式主義。有了代理人的參與,他們 是 真正的工作。