iT邦幫忙

2026 iThome 鐵人賽

DAY 8
0
Software Development

AI 時代的 TDD:讓 AI 寫 Code,但不要讓它決定品質系列 第 8

Day 08:Green 階段——AI 傾向寫出「讓測試通過的最小手段」

  • 分享至 

  • xImage
  •  

前言:「用最少的程式碼讓測試通過」,這句話不是每個人聽起來都一樣

「Kent Beck 自己都說了,Green 階段就是要用最簡單的方式讓測試通過,AI 這樣做有什麼問題?」

這句話本身沒有講錯。但「最簡單的方式」在人類 TDD 實踐者手裡,跟在 AI 手裡,長出來的東西可能完全不一樣。今天要講的,正是第二部要處理的核心問題:AI 遵守了 TDD 每一個步驟的表面規則,卻可能在每一步都悄悄地把規則的精神抽換掉。Green 階段是第一個容易被抽換的地方。

今日目標

  • 理解 Green 階段「最小實作」的原始精神是什麼,為什麼是刻意設計的紀律
  • 看懂「最小實作」跟「作弊式通過」這兩件事,表面上長得多像
  • 認識 AI 為什麼特別容易把兩者搞混
  • 掌握一組具體的判斷方法,分辨眼前的實作是不是真的在往正確方向前進
  • 建立 Green 階段之後、進入 Refactor 之前該做的檢查習慣

Green 階段的原始精神:故意先寫爛,是為了看清楚方向

Kent Beck 在《Test-Driven Development: By Example》裡描述的 Green 階段,核心精神是「先用最快的方式讓測試變綠,哪怕實作看起來很蠢」——常見的手法包括直接回傳常數(fake it)、或是先處理眼前這一個具體案例、之後再靠增加測試案例逼出更通用的邏輯(triangulation)。這聽起來像是在鼓勵偷懶,但它其實是一種刻意的紀律:先確認「測試框架、待測介面、呼叫方式」這整條路徑是通的,再去煩惱「邏輯對不對」,把兩個問題分開處理,而不是一次扛兩個未知數。

對一個有經驗的人類工程師來說,這個「先寫最簡單的版本」的動作,心裡是清楚知道自己在做什麼的——知道這只是暫時的、知道 Refactor 階段會回來把它變成真正的實作、知道如果不趕快補上更多測試案例,這個假實作會一直騙過測試。這個「心裡有數」的部分,才是 Green 階段真正的精神,不是那個看起來很蠢的實作本身。

AI 容易搞混的地方:把「暫時的簡化」變成「終點」

AI 在 Green 階段接手一個任務時,看到的只是「有一個失敗的測試,我要讓它變綠」這個目標。它會自動朝著「用最少改動達成這個目標」前進——但這個「最少改動」的判斷基準,是純粹的語法/邏輯層面:怎麼改能讓斷言為真,而不是「這個改法符合待測邏輯的真實意圖嗎」。

問題在於,人類寫 fake it 的時候,知道那是假的,會主動記得回來補;AI 寫出同樣的程式碼時,沒有「這只是暫時的」這個內在狀態——它只知道測試綠了,任務完成。同一段程式碼,人類寫是刻意的暫時手段,AI 寫可能就是終點,差別不在程式碼本身,在於寫的人有沒有意識到這只是路上的一步。

具體來說,這會有兩種常見的偏差樣貌:

偏差一:把測試斷言的期望值直接搬進實作。如果測試斷言 calculateDiscount(100, 'VIP') == 20,AI 有一定機率寫出一個直接判斷輸入是不是這組特定數值、符合就回傳 20 的實作,而不是真正實作「VIP 會員打八折」這條規則。這在只有一個測試案例時完全看不出差異——兩種寫法都讓測試變綠。

偏差二:實作邏輯只覆蓋測試涵蓋到的分支,其他分支留空或用預設值頂著。這不是刻意作弊,而是 AI 對「這個函式的完整規格是什麼」缺乏測試以外的資訊來源——它沒有辦法像人類一樣,從需求文件或業務常識推斷「這裡應該還有其他情況」,測試斷言了什麼,就是它認知裡的全部規格。

用一組對照來看這個差異:

❌ 讓測試通過的最小手段(作弊式):
function calculateDiscount(amount, memberLevel) {
  if (amount === 100 && memberLevel === 'VIP') {
    return 20
  }
  return 0
}
→ 測試綠燈,但完全沒有實作「VIP 會員打八折」這條規則,
  只是記住了測試斷言的那一組具體數字

✅ 符合規則意圖的最小實作:
function calculateDiscount(amount, memberLevel) {
  if (memberLevel === 'VIP') {
    return amount * 0.2
  }
  return 0
}
→ 測試一樣綠燈,但這是「VIP 打八折」這條規則的
  最簡單、但正確的實作,換一組輸入依然成立

這兩段程式碼對著同一個測試案例都是綠燈,差別只有換一組輸入之後才會現形——而「換一組輸入才看得出差異」,正是這個問題危險的地方:它不會在當下被發現。

怎麼分辨眼前的實作是不是真的走在正確方向上

有一個簡單但有效的判斷方法:寫完 Green 階段的實作後,故意在心裡(或實際)換一組不同的輸入問自己「這段程式碼還會給出正確答案嗎」,而不是只看測試套件裡那一組。 如果答案是「不確定」或「要看情況」,代表這個實作很可能只是在應付眼前這個測試案例,而不是真正實作了規則。

另一個更系統性的做法,是刻意增加第二個、第三個測試案例(也就是 triangulation 的精神),逼實作從「應付單一案例」進化成「處理通用規則」。如果加了第二個案例之後,AI 需要大幅改寫實作邏輯而不是簡單擴充,這本身就是一個訊號:第一版實作從一開始就走錯方向了。

今日思考題

回想你上一次讓 AI 幫你完成一個測試通過的實作:你有沒有換一組跟測試案例不同的輸入,實際跑過一次驗證?如果沒有,你怎麼確定測試綠燈代表的是「邏輯對了」,還是「剛好應付過去了」?

今日重點回顧

  • Green 階段的原始精神是「先確認路徑通了,再處理邏輯對不對」,而不是「用任何手段讓測試變綠都可以」
  • 人類寫最小實作時心裡知道那是暫時的,AI 沒有這個內在狀態,測試綠了就等於任務完成
  • 兩種常見偏差:把測試期望值直接搬進實作、實作只覆蓋測試涵蓋到的分支
  • 判斷方法:換一組不同輸入問「這段程式碼還會對嗎」,或刻意增加案例逼出真正的通用邏輯

明日預告

明天用一個具體案例,示範 AI 為了讓測試綠燈,直接把測試斷言的期望值硬編碼進實作——一個比今天講的更明顯、也更容易被忽略的真實樣貌。


上一篇
Day 07:為什麼「先看紅燈」比「有沒有寫測試」更重要
下一篇
Day 09:案例——AI 為了讓測試綠燈,硬編碼了預期值
系列文
AI 時代的 TDD:讓 AI 寫 Code,但不要讓它決定品質9
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言