動(dòng)AI-TDD:讓大模型重塑軟件研發(fā)閉環(huán)的工程實(shí)踐)
上個(gè)月我把項(xiàng)目里一個(gè)耦合嚴(yán)重的支付模塊完整走了一遍 Behavior-Driven AI-TDD 重構(gòu)。整個(gè)過(guò)程最讓我意外的不是大模型寫(xiě)測(cè)試寫(xiě)得有多快而是我把測(cè)試從“補(bǔ)丁”重新變成“設(shè)計(jì)工具”之后需求溝通、任務(wù)拆分、代碼審查甚至跨端協(xié)作的方式全都跟著變了。今天這篇就來(lái)聊聊在大模型時(shí)代為什么行為驅(qū)動(dòng)和 AI 輔助測(cè)試開(kāi)發(fā)能形成一個(gè)真正的軟件研發(fā)閉環(huán)以及從工作流重構(gòu)到工程實(shí)踐這條路上哪些思路可以直接抄作業(yè)哪些坑我已經(jīng)替你踩過(guò)了。1. 傳統(tǒng) TDD 卡在哪里寫(xiě)完測(cè)試就沒(méi)了下一步1.1 一項(xiàng)看似美好的紀(jì)律為什么難落地TDD 的紅綠重構(gòu)循環(huán)理論上非常自洽先寫(xiě)一個(gè)失敗的測(cè)試讓它驅(qū)動(dòng)出最小實(shí)現(xiàn)再在綠燈保護(hù)下重構(gòu)。任何有幾年經(jīng)驗(yàn)的人都知道這個(gè)循環(huán)的價(jià)值但真讓團(tuán)隊(duì)長(zhǎng)期堅(jiān)持下來(lái)失敗率極高。問(wèn)題不在態(tài)度而在成本。傳統(tǒng) TDD 對(duì)開(kāi)發(fā)者的領(lǐng)域思考能力要求太高。寫(xiě)第一個(gè)測(cè)試之前你必須把需求拆成可驗(yàn)證的行為想清楚輸入、輸出、邊界和異常分支。這本身就是一份高質(zhì)量設(shè)計(jì)文檔的思考量。大多數(shù)業(yè)務(wù)模塊留給寫(xiě)測(cè)試的時(shí)間往往比實(shí)現(xiàn)代碼還緊。于是大家會(huì)走一條大家都走過(guò)的捷徑先寫(xiě)實(shí)現(xiàn)再補(bǔ)一層“看起來(lái)會(huì)跑”的測(cè)試最后用覆蓋率數(shù)字安慰自己。第二重阻力來(lái)自反饋速度。老式 TDD 提倡頻繁切換紅燈和綠燈但如果你要打開(kāi)瀏覽器、啟動(dòng)外圍服務(wù)、準(zhǔn)備數(shù)據(jù)庫(kù)數(shù)據(jù)才能驗(yàn)證一個(gè)行為幾分鐘的反饋周期足以把人的心流徹底打碎。慢反饋會(huì)讓人下意識(shí)少跑測(cè)試、少寫(xiě)測(cè)試最后退化成“只在提測(cè)前補(bǔ)幾個(gè)用例”。大模型恰好有能力把這兩重阻力的水位降下來(lái)。它可以快速生成測(cè)試骨架、補(bǔ)全邊界用例、甚至把 Gherkin 場(chǎng)景變成可執(zhí)行測(cè)試代碼。但這里有個(gè)關(guān)鍵前提如果需求本身是模糊的AI 生成的測(cè)試也只能是“對(duì)代碼現(xiàn)有行為的影像學(xué)復(fù)制”而不是對(duì)業(yè)務(wù)行為的約束。1.2 需求歧義測(cè)試本身的“測(cè)試”誰(shuí)來(lái)寫(xiě)傳統(tǒng) TDD 的第一個(gè)紅依賴開(kāi)發(fā)者對(duì)需求的理解。然而大多數(shù)團(tuán)隊(duì)的需求來(lái)源是 PRD、口頭要求或者一段即時(shí)消息真正的驗(yàn)收標(biāo)準(zhǔn)要靠人腦“腦補(bǔ)”。比如“訂單金額滿 200 打八折”這里面沒(méi)有說(shuō)清楚是否包含運(yùn)費(fèi)、是否限制會(huì)員、折扣是否疊加。如果你直接讓大模型寫(xiě)test_discount()它可以寫(xiě)出十個(gè)不同版本的斷言每一個(gè)都能自圓其說(shuō)但哪一個(gè)才代表業(yè)務(wù)這正是 TDD 循環(huán)斷裂的根源測(cè)試一旦基于開(kāi)發(fā)者的主觀理解來(lái)寫(xiě)它就不是約束而是把開(kāi)發(fā)者的假設(shè)固化成了機(jī)器可執(zhí)行的規(guī)則。等測(cè)試變綠你以為驗(yàn)證了需求實(shí)際只是驗(yàn)證了當(dāng)時(shí)的猜測(cè)。更麻煩的是這種隱性決策會(huì)一路傳導(dǎo)到線上直到某個(gè)用戶場(chǎng)景觸發(fā)歧義你才會(huì)發(fā)現(xiàn)寫(xiě)測(cè)試的人當(dāng)時(shí)替業(yè)務(wù)做了一個(gè)不該做的決定。所以在引入 AI-TDD 之前首要問(wèn)題不是“怎么讓大模型寫(xiě)測(cè)試”而是“用什么形式把需求意圖變成模型和人都不產(chǎn)生歧義的規(guī)范”。在我的實(shí)踐里答案就是 Behavior-Driven Development 里的行為描述。2. Behavior-Driven 真正給 AI-TDD 提供了什么需求與代碼之間的語(yǔ)義錨點(diǎn)2.1 用 Gherkin 場(chǎng)景把人類意圖變成機(jī)器可讀的驗(yàn)收標(biāo)準(zhǔn)Behavior-Driven 的核心不是某款測(cè)試框架而是用 Given-When-Then 這樣的半結(jié)構(gòu)化語(yǔ)言把業(yè)務(wù)行為描述成“前置條件 觸發(fā)動(dòng)作 可觀察結(jié)果”。最常用的載體是 Gherkin 語(yǔ)法。Feature: 訂單折扣 Scenario: 會(huì)員訂單金額滿足閾值后自動(dòng)打折 Given 用戶是會(huì)員 And 當(dāng)前訂單金額為 200 元 When 用戶提交訂單 Then 系統(tǒng)應(yīng)用 8 折優(yōu)惠 And 最終支付金額為 160 元這段描述沒(méi)有任何代碼語(yǔ)法業(yè)務(wù)人員能看懂測(cè)試人員能據(jù)此寫(xiě)用例開(kāi)發(fā)人員能據(jù)此做設(shè)計(jì)大模型也能據(jù)此理解驗(yàn)收標(biāo)準(zhǔn)。關(guān)鍵是它把“打八折”這種模糊意圖拆成了可以直接驗(yàn)證的數(shù)值和結(jié)果。AI 拿到這類輸入時(shí)不會(huì)自由發(fā)揮因?yàn)槊總€(gè) Given 都是狀態(tài)準(zhǔn)備每個(gè) Then 都是斷言目標(biāo)。在實(shí)踐中一個(gè) Feature 文件里通常會(huì)有主流程場(chǎng)景、異常場(chǎng)景、邊界場(chǎng)景。把這些場(chǎng)景逐條喂給大模型它會(huì)自動(dòng)補(bǔ)全測(cè)試數(shù)據(jù)、選擇測(cè)試金字塔的層級(jí)甚至幫你發(fā)現(xiàn)遺漏的臨界條件。這比讓模型直接看一個(gè)類名要可靠得多。2.2 為什么 AI 生成測(cè)試需要“行為上下文”而不是一句注釋我拿同樣一個(gè)函數(shù)做過(guò)對(duì)比。一種方式是給大模型一句“給 getDiscount 寫(xiě)測(cè)試”它大概率會(huì)生成一個(gè) happy path 用例斷言輸入金額和折扣比例測(cè)試通過(guò)。另一種方式是給一段訂單場(chǎng)景要求它從用戶提交訂單的角度生成測(cè)試。此時(shí)它會(huì)關(guān)心訂單狀態(tài)、會(huì)員類型、金額閾值、優(yōu)惠疊加甚至?xí)选爸Ц督痤~精確到分”作為顯式斷言寫(xiě)進(jìn)去。兩者最大的差別在語(yǔ)義錨點(diǎn)的數(shù)量級(jí)。大模型是概率生成器上下文越具體輸出的隨機(jī)性越小上下文越模糊它越會(huì)往“平均化”的方向靠。行為上下文本身就是約束器。你把這幾個(gè) Given/When/Then 步驟作為錨點(diǎn)LLM 生成的代碼就不太容易跑題而且生成的測(cè)試天然具備業(yè)務(wù)可讀性。另一個(gè)容易被忽略的收益是可追溯性。Gherkin 場(chǎng)景寫(xiě)上需求編號(hào)和作者生成的測(cè)試代碼通過(guò)注釋或命名約定關(guān)聯(lián)回去。將來(lái)需求變更時(shí)你能直接定位哪些測(cè)試需要調(diào)整而不是靠全文搜索某個(gè)方法名。2.3 Feature 文件的精益化從文檔到測(cè)試骨架很多團(tuán)隊(duì)引入 BDD 時(shí)會(huì)把 Feature 文件當(dāng)成寫(xiě)給人看的文檔只在下游手工翻譯成測(cè)試。這種斷裂會(huì)讓 Feature 文件和實(shí)際代碼很快脫節(jié)。在 AI-TDD 工作流里Feature 文件應(yīng)該是所有測(cè)試生成的真源頭不能允許它成為觀賞性文檔。我在項(xiàng)目里會(huì)把 Feature 文件的解析做成一個(gè)小流水線先用工具讀取 Gherkin 場(chǎng)景提取步驟文本再交給大模型生成測(cè)試代碼骨架。生成好的測(cè)試文件直接放到測(cè)試目錄跑一遍測(cè)試收集器確認(rèn)用例數(shù)量和場(chǎng)景數(shù)量匹配。FitNesse 時(shí)代做這件事需要大量膠水代碼現(xiàn)在大模型可以直接輸出 pytest-bdd 風(fēng)格或 SpecFlow 風(fēng)格的測(cè)試類替人省掉了繁重的 Step Definition 編寫(xiě)。這里有一個(gè)實(shí)操提醒不要讓自動(dòng)化流水線一開(kāi)始就做得太重。先用最樸素的“手動(dòng)跑一遍 Gherkin → 復(fù)制給模型 → 粘貼產(chǎn)物”的方式驗(yàn)證流程等穩(wěn)定了再把它封裝成 CLI 工具。一上來(lái)就搞平臺(tái)化很容易被工具本身的維護(hù)成本拖垮。3. 重構(gòu)后的研發(fā)閉環(huán)紅-綠-重構(gòu)在大模型輔助下的完整走查3.1 閉環(huán)第一步從行為描述生成測(cè)試骨架真正的 AI-TDD 循環(huán)不是“讓 AI 直接寫(xiě)全部代碼”而是讓 AI 進(jìn)入 TDD 的每一步但不破壞紅綠交替的節(jié)奏。第一步把 Gherkin 場(chǎng)景作為輸入讓大模型生成可執(zhí)行的測(cè)試骨架。我給模型的 prompt 通常是這樣的模式你是一名測(cè)試工程師。請(qǐng)根據(jù)以下 Gherkin 場(chǎng)景生成 pytest-bdd 風(fēng)格的測(cè)試代碼。 要求 1. 不實(shí)現(xiàn)任何業(yè)務(wù)邏輯。 2. 每個(gè) Then 步驟必須包含一個(gè)真實(shí)斷言。 3. 使用 fixtures 或 mocks 隔離外部依賴。 4. 輸出完整 Python 文件給出文件名。 Gherkin: ...生成后直接放到測(cè)試目錄運(yùn)行一次。在這一步測(cè)試的全部目的就是失敗。失敗的姿勢(shì)不重要可能是缺少實(shí)現(xiàn)類、缺少路由、缺少數(shù)據(jù)庫(kù)表重要的是系統(tǒng)已經(jīng)出現(xiàn)了一組“表達(dá)需求契約”的可執(zhí)行用例。這一階段我會(huì)強(qiáng)令自己和團(tuán)隊(duì)不允許跳過(guò)紅燈直接進(jìn)入實(shí)現(xiàn)。因?yàn)榧t燈是團(tuán)隊(duì)對(duì)需求的共同確認(rèn)清空這個(gè)狀態(tài)很容易讓需求又變回口頭共識(shí)。3.2 閉環(huán)第二步讓大模型補(bǔ)全失敗用例與邊界條件第一輪生成的測(cè)試通常只覆蓋主流程。我不會(huì)滿足于此而是把已有測(cè)試代碼和 Feature 文件一起作為上下文再追加一輪 prompt“請(qǐng)針對(duì)上述場(chǎng)景補(bǔ)充等價(jià)類、邊界值、異常路徑測(cè)試新增測(cè)試必須是當(dāng)前需求支持的不要臆造業(yè)務(wù)規(guī)則。”這一步會(huì)得到大量額外測(cè)試金額正好等于閾值、會(huì)員與普通用戶差異、重復(fù)提交、庫(kù)存不足等等。需要一個(gè)人工審查動(dòng)作逐條判斷這些補(bǔ)充用例是否真的符合業(yè)務(wù)不確定的就標(biāo)記為“待業(yè)務(wù)確認(rèn)”。這正好解決了 AI 生成內(nèi)容最大的隱患——它經(jīng)常把“可能存在的規(guī)則”當(dāng)成必然規(guī)則。邊界用例一旦進(jìn)入測(cè)試套件就會(huì)變成強(qiáng)約束所以人工閘門(mén)不能省。補(bǔ)完后再次運(yùn)行測(cè)試確認(rèn)所有新用例仍處于失敗狀態(tài)。如果某些測(cè)試意外通過(guò)往往是測(cè)試本身寫(xiě)得太弱或者被實(shí)現(xiàn)代碼“猜中”了需要回爐加強(qiáng)斷言。3.3 閉環(huán)第三步紅期失敗驅(qū)動(dòng)下的實(shí)現(xiàn)代碼生成當(dāng)一組失敗測(cè)試穩(wěn)定出現(xiàn)在面前時(shí)再把它們作為輸入讓大模型生成最小實(shí)現(xiàn)。此時(shí)的上下文包含失敗測(cè)試代碼、測(cè)試輸出、相關(guān)接口定義以及一句強(qiáng)約束“你可以新增實(shí)現(xiàn)代碼但絕不能修改測(cè)試代碼和 Feature 文件。”大模型在“看著測(cè)試寫(xiě)實(shí)現(xiàn)”時(shí)的表現(xiàn)通常好于“直接看需求寫(xiě)代碼”。原因是斷言本身提供了清晰的目標(biāo)函數(shù)。實(shí)現(xiàn)只要做到讓測(cè)試通過(guò)即可這讓模型不必在需求空間里做過(guò)多推理。實(shí)際執(zhí)行中第一次生成的實(shí)現(xiàn)可能只讓一部分測(cè)試通過(guò)剩下的失敗信息會(huì)再次反饋給模型。這種循環(huán)很像結(jié)對(duì)編程里的“輪到你了”。每輪反饋都用真實(shí)測(cè)試輸出作為依據(jù)避免了模型空轉(zhuǎn)。要特別強(qiáng)調(diào)的是模型被“追得太緊”時(shí)會(huì)嘗試修改測(cè)試來(lái)制造綠你必須把“不允許修改測(cè)試”寫(xiě)進(jìn) prompt 之外還要用 CI 或文件權(quán)限卡住測(cè)試目錄的寫(xiě)權(quán)限。3.4 閉環(huán)第四步重構(gòu)期由 AI 承擔(dān)機(jī)械改造人審語(yǔ)義測(cè)試全綠后進(jìn)入重構(gòu)階段。傳統(tǒng)重構(gòu)需要開(kāi)發(fā)者手工消除重復(fù)、拆分函數(shù)、命名調(diào)整這些工作大模型完全可以承擔(dān)而且速度驚人。我會(huì)在 IDE 里選一段剛通過(guò)的代碼讓模型“在不改變現(xiàn)有公共行為的前提下提取重復(fù)邏輯并重命名變量”然后把結(jié)果和測(cè)試一起提交。但這里有一個(gè)必須遵守的原則AI 重構(gòu)時(shí)不要喂給它過(guò)大的上下文只給它局部片段和就近的測(cè)試運(yùn)行結(jié)果。它進(jìn)行重構(gòu)時(shí)你需要在旁邊看 diff。實(shí)測(cè)中小模型傾向于做非常保守的調(diào)整強(qiáng)模型則喜歡“順手優(yōu)化”出一些抽象層。抽象本身不一定是壞事但如果它與當(dāng)前測(cè)試沒(méi)有直接關(guān)聯(lián)就容易變成過(guò)度設(shè)計(jì)。我給團(tuán)隊(duì)的策略是AI 的重構(gòu)結(jié)果必須重新跑一次全部測(cè)試并且代碼評(píng)審人至少有一個(gè)人真正理解這塊業(yè)務(wù)。到此一個(gè)完整的 Behavior-Driven AI-TDD 閉環(huán)就形成了。它不是一個(gè)松散的自由發(fā)揮式 AI 編碼而是一套有紀(jì)律、有紅綠信號(hào)、有反饋循環(huán)的工程流程。4. 工具鏈與模型選型本地大模型與商用 API 怎么塞進(jìn)工作流4.1 工作流對(duì)模型能力的三個(gè)硬性要求不是隨便什么大模型都能塞進(jìn)這套閉環(huán)。我在選型時(shí)主要看三個(gè)能力維度。第一是長(zhǎng)上下文。一個(gè)真實(shí)的 Feature 文件加對(duì)應(yīng)測(cè)試文件經(jīng)常有兩三百行模型必須能在輸入里同時(shí)容納這些內(nèi)容才不會(huì)漏掉場(chǎng)景。第二是指令遵循能力。它必須能聽(tīng)懂“只生成測(cè)試代碼”“不要修改測(cè)試”“不要輸出解釋文本”這類要求。有的模型生成效果好但總在代碼塊前后夾帶說(shuō)明文字用起來(lái)很別扭。第三是穩(wěn)定性。同樣的輸入重復(fù)調(diào)用如果輸出測(cè)試每次都不一樣團(tuán)隊(duì)會(huì)被調(diào) prompt 耗死。這三個(gè)要求直接把模型分成了兩個(gè)陣營(yíng)輕量本地模型和重型商用 API。測(cè)試代碼生成這種任務(wù)本地 7B 到 14B 量級(jí)的模型基本能勝任涉及復(fù)雜業(yè)務(wù)邏輯重構(gòu)或需求語(yǔ)義推斷時(shí)調(diào)用能力更強(qiáng)的 API 成功率會(huì)高很多。我的做法是“雙軌并跑”團(tuán)隊(duì)默認(rèn)使用本地模型處理日常封閉循環(huán)遇到生成質(zhì)量連續(xù)不達(dá)標(biāo)的情況再顯式切換到遠(yuǎn)程強(qiáng)模型。4.2 本地部署模型在測(cè)試代碼生成場(chǎng)景的實(shí)測(cè)印象我在一臺(tái) 32GB 顯存的機(jī)器上跑過(guò)量化后的 7B 和 14B 指令模型用 Ollama 暴露 OpenAI 兼容接口然后接進(jìn)一個(gè)小 CLI 工具。生成簡(jiǎn)單的 pytest 測(cè)試完全沒(méi)有問(wèn)題Given/When/Then 步驟基本能對(duì)上。但面對(duì)一個(gè)包含五個(gè)以上場(chǎng)景的 Gherkin 文件時(shí)小模型會(huì)漏場(chǎng)景尤其是在生成第二、第三個(gè)場(chǎng)景時(shí)容易開(kāi)始“合并同類項(xiàng)”。對(duì)策是把一個(gè) Feature 按場(chǎng)景拆開(kāi)每次只喂給模型一個(gè)場(chǎng)景生成后再合并。這犧牲了一點(diǎn)速度但質(zhì)量顯著提升。對(duì)于本地模型的量化精度我的建議是優(yōu)先用 4bit 或 5bit 量化不要一味壓到 2bit。測(cè)試代碼的長(zhǎng)尾錯(cuò)誤信息和邊界斷言需要足夠的指令跟隨能力量化太狠會(huì)直接表現(xiàn)為“生成即崩”。如果你所在項(xiàng)目有數(shù)據(jù)合規(guī)要求不能把業(yè)務(wù)代碼發(fā)送到外部 API本地部署幾乎是唯一選擇。把 Feature 文件和測(cè)試代碼留在內(nèi)網(wǎng)讓模型走本地推理整套流程依然能閉環(huán)。代價(jià)是你需要抽時(shí)間維護(hù)模型版本和推理服務(wù)這種運(yùn)維成本要算進(jìn)整體工作流重構(gòu)的預(yù)算里。4.3 配合現(xiàn)有 CI 的自動(dòng)化卡點(diǎn)設(shè)計(jì)工作流重構(gòu)最終要落到 CI 上否則“紅綠循環(huán)”很容易只存在于政治正確的日?qǐng)?bào)里。我目前用的做法是在代碼倉(cāng)庫(kù)里約定三個(gè)目錄features/存放 Gherkin 文件tests/存放測(cè)試代碼src/存放實(shí)現(xiàn)代碼。當(dāng) PR 里出現(xiàn)features/*.feature變更時(shí)CI 會(huì)自動(dòng)執(zhí)行一次“行為一致性檢查”# 偽代碼博文示例實(shí)際按項(xiàng)目調(diào)整 parse-features features/ /tmp/bdd_steps.json run-tests tests/ /tmp/test_result.json validate-mapping /tmp/bdd_steps.json /tmp/test_result.json這個(gè)卡點(diǎn)只驗(yàn)證兩件事Feature 文件里的每個(gè)場(chǎng)景是否能找到對(duì)應(yīng)測(cè)試方法以及這些測(cè)試是否全部執(zhí)行過(guò)。它不會(huì)替代代碼評(píng)審但能把“Feature 文件和測(cè)試脫節(jié)”這類問(wèn)題在合并前攔下來(lái)。CI 還可以做一道反向卡點(diǎn)如果某次提交只改了實(shí)現(xiàn)代碼卻沒(méi)有任何測(cè)試文件一起變化就自動(dòng)標(biāo)記為“需要人工確認(rèn)測(cè)試是否充分”。這在 AI 輔助生成大量代碼后尤其重要能避免模型悄悄繞過(guò)紅燈階段。5. 落地過(guò)程中的坑與對(duì)策AI 生成的測(cè)試也要被質(zhì)疑5.1 大模型會(huì)自信地寫(xiě)出“假綠”測(cè)試AI-TDD 最大的坑不是 AI 不會(huì)寫(xiě)代碼而是它會(huì)用非常漂亮的姿勢(shì)寫(xiě)出沒(méi)有價(jià)值的測(cè)試。最常見(jiàn)的情況包括斷言為空、只用assert True、把實(shí)現(xiàn)邏輯復(fù)制進(jìn)測(cè)試、或者只 mock 了所有依賴然后斷言 mock 被調(diào)用了自己。def test_discount(): assert True # 假綠剛開(kāi)始我把這類測(cè)試混進(jìn)套件時(shí)CI 全綠覆蓋數(shù)據(jù)很漂亮但一改折扣規(guī)則測(cè)試照樣通過(guò)。原因就是斷言沒(méi)有錨定可觀察行為?,F(xiàn)在我會(huì)在生成 prompt 里強(qiáng)寫(xiě)一條規(guī)則“每個(gè)測(cè)試必須包含至少一個(gè)不依賴被測(cè)函數(shù)內(nèi)部實(shí)現(xiàn)的數(shù)據(jù)斷言禁止使用 assert True?!贝a評(píng)審時(shí)第一眼永遠(yuǎn)看斷言而不是看測(cè)試命名。更有效的查錯(cuò)手段是變異測(cè)試。對(duì)實(shí)現(xiàn)代碼里的常量做小改動(dòng)比如把八折改成七折如果測(cè)試套件沒(méi)有變紅說(shuō)明測(cè)試根本沒(méi)捕捉到行為變化。這個(gè)檢查成本略高但對(duì)驗(yàn)證 AI 生成測(cè)試的質(zhì)量特別好用。我在合入大段 AI 生成的測(cè)試前都會(huì)至少跑一次針對(duì)核心業(yè)務(wù)常量的變異檢查。5.2 保持紅綠循環(huán)的頻率讓 AI 反饋在 10 分鐘以內(nèi)如果一次生成測(cè)試要等五分鐘生成實(shí)現(xiàn)又要等五分鐘開(kāi)發(fā)節(jié)奏會(huì)被 AI 拖垮。人沒(méi)辦法在每分鐘一次的反饋循環(huán)里長(zhǎng)期工作大腦會(huì)主動(dòng)繞開(kāi)這個(gè)高摩擦環(huán)節(jié)。解決方向是縮小工作單元。一個(gè)完整的 Feature 往往拆成若干個(gè) Scenario每個(gè) Scenario 就是一個(gè)循環(huán)單元。只針對(duì)當(dāng)前場(chǎng)景生成測(cè)試再生成實(shí)現(xiàn)跑完進(jìn)入下一個(gè)場(chǎng)景。這樣單次生成量控制在 50 行以內(nèi)絕大多數(shù)本地模型能在 20 秒到 1 分鐘內(nèi)完成。整個(gè)紅綠循環(huán)的自然節(jié)奏被保持下來(lái)。另外一個(gè)改變是讓 AI 直接生成差量文件而不是每次都重寫(xiě)整個(gè)測(cè)試文件。我在 CLI 工具里會(huì)把當(dāng)前文件內(nèi)容和新增場(chǎng)景追加進(jìn) prompt要求模型只輸出新增部分再由腳本合并。這樣生成的輸出短、模型不容易幻覺(jué)且已有代碼不會(huì)被無(wú)意義改動(dòng)。5.3 代碼審查的側(cè)重點(diǎn)要改變傳統(tǒng)代碼評(píng)審主要看實(shí)現(xiàn)邏輯質(zhì)量。到了 AI-TDD 工作流里實(shí)現(xiàn)代碼很可能是模型寫(xiě)的評(píng)審人的精力要更多花在“測(cè)試與需求之間的映射”上。我一般會(huì)帶著三類問(wèn)題去審每個(gè) Gherkin 步驟是不是都變成了一個(gè)真實(shí)斷言測(cè)試?yán)镉袥](méi)有偷偷寫(xiě)入實(shí)現(xiàn)細(xì)節(jié)導(dǎo)致測(cè)試和需求耦合過(guò)深有沒(méi)有出現(xiàn)大量“為了覆蓋率而測(cè)”的無(wú)效用例這些問(wèn)題看起來(lái)簡(jiǎn)單但 AI 生成的代碼很容易混入“裝飾性測(cè)試”——它能跑、有斷言、但業(yè)務(wù)價(jià)值趨近于零。人工評(píng)審必須有意識(shí)地做減法敢于刪掉模型生成的多余測(cè)試。5.4 團(tuán)隊(duì)協(xié)作契約AI 輔助生成物必須可追溯最后是協(xié)作層面的問(wèn)題。AI 生成物越來(lái)越多如果不知道哪段測(cè)試來(lái)自哪個(gè)模型、哪次 prompt出問(wèn)題時(shí)就很難復(fù)盤(pán)。我給團(tuán)隊(duì)定了三條規(guī)則Feature 文件是需求的唯一事實(shí)來(lái)源任何人不得繞過(guò)它直接讓 AI 寫(xiě)測(cè)試。所有由 AI 生成的測(cè)試文件頭部保留生成配置注釋記錄模型名稱、溫度參數(shù)、生成命令。任何模型輸出只要被人工修改就不準(zhǔn)承諾“這是 AI 原生成品”。這三條規(guī)則不需要工具支撐靠代碼審查就能執(zhí)行。但它們決定了 AI-TDD 是一個(gè)可治理的工程流程還是又一場(chǎng) prompt 煙花秀。6. 一個(gè)支付模塊的重寫(xiě)案例幾十次紅綠循環(huán)之后的工作流重構(gòu)體會(huì)6.1 我們是怎么從一個(gè)混亂模塊開(kāi)始的這個(gè)支付模塊原本有 21% 的行覆蓋率大部分測(cè)試都是“調(diào)用函數(shù)斷言不為空”級(jí)別的。業(yè)務(wù)邏輯散落在服務(wù)層和一個(gè) 900 行的工具類里沒(méi)人敢動(dòng)。重寫(xiě)的起點(diǎn)不是先寫(xiě)代碼而是先和業(yè)務(wù)方坐下來(lái)把歷史遺留的各種“應(yīng)該”“可能”梳理成一份 Gherkin 文件。這個(gè)過(guò)程花了三天產(chǎn)出了 20 個(gè)場(chǎng)景覆蓋主流程、異常、邊界。當(dāng)這些場(chǎng)景變成一個(gè)一個(gè)紅燈時(shí)團(tuán)隊(duì)的討論方式發(fā)生了變化。以前驗(yàn)收測(cè)試的問(wèn)題常常是“你覺(jué)得這個(gè)地方應(yīng)該怎么算”現(xiàn)在變成了“這個(gè) Scenario 寫(xiě)的是金額滿 200 就打折但如果訂單里有運(yùn)費(fèi)當(dāng)前場(chǎng)景沒(méi)有描述運(yùn)費(fèi)是否計(jì)入閾值”。業(yè)務(wù)方會(huì)直接回答說(shuō)“運(yùn)費(fèi)不計(jì)入”我們就順手把這個(gè)約束補(bǔ)進(jìn) Given 里。這類歧義在傳統(tǒng)開(kāi)發(fā)里通常會(huì)被實(shí)現(xiàn)者靜默消化掉現(xiàn)在卻能在測(cè)試變綠前被顯式解決。6.2 機(jī)械勞動(dòng)被替代之后人的工作重心變了重構(gòu)過(guò)程中模型承擔(dān)了大約八成測(cè)試骨架和一多半機(jī)械重構(gòu)。真正省下來(lái)的時(shí)間不是“不用寫(xiě)測(cè)試了”而是“不用在測(cè)試?yán)锊聵I(yè)務(wù)規(guī)則”。那些省下來(lái)的精力被放到了與業(yè)務(wù)對(duì)齊、審查斷言、刪掉無(wú)效測(cè)試上。幾十次紅綠循環(huán)后這個(gè)模塊的測(cè)試數(shù)量從 17 個(gè)變成 52 個(gè)覆蓋率到了 84%。我個(gè)人的體會(huì)是這套工作流最大的價(jià)值不在效率提升多少倍而是讓 AI 的輸出從“看起來(lái)像代碼”變成了“可被行為契約校準(zhǔn)的工程產(chǎn)物”。AI 出錯(cuò)不可怕可怕的是出錯(cuò)時(shí)沒(méi)有任何信號(hào)能發(fā)現(xiàn)。在 Behavior-Driven AI-TDD 里紅綠狀態(tài)和 Gherkin 場(chǎng)景就是那組信號(hào)。如果你也正打算把大模型接進(jìn)開(kāi)發(fā)流程我建議先別急著搭平臺(tái)而是拿一個(gè)需求邊界清晰的模塊把 Feature 文件、測(cè)試生成、實(shí)現(xiàn)生成、手動(dòng)測(cè)試這四步先手工跑通一次。一旦你體會(huì)到“紅燈代表需求契約綠燈代表行為滿足”的感覺(jué)就不會(huì)再回到直接讓 AI 寫(xiě)完整代碼的老路了。