iT邦幫忙

2026 iThome 鐵人賽

0
AI Engineering

AI 寫的測試,誰來測?系列 第 33 篇

【Day30-下】修完了,然後回答第一天那個引號

  • 分享至 

  • xImage
  •  

TL;DR

  • 四個缺陷,加上規格裁決後改寫的通膨基準年,接回那支 HTML。接回去的那份跟 Python 實作逐位元對齊:505 組輸入、2005 項比對、0 不符
  • 活了十天的變異體 M14,靠一條「通膨率與收入如何交互」的關係殺掉——那條關係只有一句話,但需要一組從來沒人餵過的輸入
  • 三十天回答「誰來測」:人造尺、人讀原始碼、人做決定;AI 補得動的是輸入涵蓋

https://ithelp.ithome.com.tw/upload/images/20261001/20103826vumxVutlKF.jpg


前言

第一天的標題是:我的退休試算上線一年,我檢查過,它「沒問題」?

那個引號現在可以回答了。


修了什麼

Python 實作 shadow/calc_fixed.py 從第十五天起就存在,經過後面十五天所有的尺。今天做的是把它接回受測物那支 HTML,原版不動,另存 v2。

缺陷 改法 依據 哪一天確認
A 少算一個 (1+r) 折現與提領改期初,第一期對應退休當年 PRD-02/03 Day 4 推導;Day 25 對帳關係在舊版上紅,比值精確等於 1.04
A' 圖表夾 0 移除 Math.max(0, ...),圖表逐項等於真實餘額 PRD-03/12 Day 26 同一條斷言在舊版第三年紅:0.00 對 −850 萬
B 壽命倒置 年齡順序不成立即拋錯,表單層阻斷 PRD-04 Day 3 驗屍
C 大筆支出無上界 限定退休至壽命區間,區間外不計入並明示 PRD-05/11 Day 3 驗屍;Day 13 界外位置會紅
D 靜默補零 parseNumber 不再 || 0,列出哪一欄不是數字 PRD-04 Day 13 指出它在抽取邊界外
通膨基準年 勞保勞退改鎖各自的請領年齡 PRD-10 Day 9 起兩次裁決

每一項都不是今天才發現的。今天只是把三十天前就該做的事做掉。

表格裡有一列跟其他五列不一樣。 缺陷 D 的 parseNumber 在 HTML 第 215 行,第十三天就寫過它在影子模型的抽取邊界外:所以底下四件驗收,沒有一件看得到它。差分比的是計算核心,快照、golden、關係也都是。v2 改了那一行,但它的驗證只有手動:開瀏覽器、把欄位清空、看有沒有跳出「以下欄位不是數字」。這一列的「修好了」,證據等級跟其他五列不同,照實標。


沒修的那個

年報酬率直接除以 12 當月利率。Day 3 就寫了:這不是缺陷,是模型假設的簡化,實測讓累積資產多算六十一萬。Day 9 閘門一裁決保留,理由與代價都在紀錄裡。

這一篇不推翻那個裁決。 變異體目錄裡有一個 M03,方向是「把 /12 改成更正確的有效月利率」,而測試殺得掉它,代表測試已經把這個簡化鎖成規格了。要改,得回閘門一重新裁決,不是在修復日順手改掉。


怎麼確認修對了

移植本身也是程式,會錯。第一幕就是這樣開始的。

四件事同時成立才准部署:

一、舊快照紅在預期處。 第七天鎖舊版行為的那套測試,拿去對修復版跑:

27 failed in 0.14s

二十三組快照全紅,四條鎖缺陷的測試全紅。二十三組裡二十一組紅的原因是缺陷 A:折現改成期初,每一組的目標金額都變了。另外兩組是壽命倒置的案例,修復版直接拋錯——那是缺陷 B。鎖 C 和 A' 的那幾組同時被兩個修復碰到。全部紅是這批案例的性質,不是通則;反過來說,有任何一組沒紅才要追:是那組本來就不受影響,還是修復漏了它。

二、新規格測試全綠。 照 PRD v1.2 寫的二十三組(二十一組鎖數值、兩組必須拋錯):

23 passed in 0.03s

三、四條關係在新舊兩版符合預期。 修復版全綠,舊版紅在對帳那條:

FAILED test_mr04_funded_exactly_closes_the_gap[legacy]
  isclose(-28813.50481278846, 0.0, abs_tol=0.001)
1 failed, 19 passed

同一個 −28,813.50,跟 Day 25 抓到缺陷 A 那天一模一樣。

四、JS 跟 Python 是同一個東西。 反向差分:Python 是規格的實作,JS 是移植,兩邊餵同樣的輸入比輸出。容許誤差沿用第一幕差分測試的 1e-9,跑前定跑完不調,不符時預設是移植錯。

反向差分|505 組輸入|rel_tol=1e-09
比對 2005 項(3 純量 + balances_raw 序列)
不符:0

第一版跑了 500 組全是合法輸入,拋錯路徑一組都沒走到——就是前兩天那個病。補五組故意違規的(年齡相等、壽命倒置、金額負值、請領年齡負值、大筆支出負值),五組兩邊同步拋錯。


那個活了十天的變異體

M14 從第二十天活到第二十八天,十份 AI 產物、142 條關係,沒有一條碰得到。

原因跟 M09 一樣,前天寫過:不是斷言的問題,是二十三組案例的 other_income 全是零。而規格早在第九天就裁決過「退休後收入隨通膨調升」,第十三天又改過一次基準年。決定做了兩次,測試沒有一組讓那個欄位非零。

Day 25 推過四類關係都碰不到它,寫了一句「要殺它需要一條關於『通膨率與收入怎麼交互』的關係。那不是套公式套得出來的,得有人真的想過」。

那個洞察只有一句話:收入若隨通膨調升,它會抵銷一部分通膨對目標金額的影響。

寫成關係:通膨率從 2% 升到 4%,有收入時目標金額的增幅,應該小於沒有收入時的增幅。收入若固定不動,兩個增幅會相等:扣的是同一個常數。

calc_fixed:Δ有收入 14,621,896 < Δ無收入 18,277,370   成立
注入 M14:  Δ有收入 18,277,370 = Δ無收入 18,277,370   不成立

注入之後兩個數字完全相等。那就是「收入沒有隨通膨調升」的簽名。

這條關係不需要知道目標金額是多少。它需要的只是一組非零的收入,和一句想清楚的話。

逐條跑十四個變異體:

test_prd10_indexed_income_offsets_part_of_inflation   殺掉 1   M14

它只殺 M14,其他十三個一個都碰不到。一條關係對一個錯法:那正是「領域洞察」長的樣子:不是抓得多,是抓得準。


誰來測

三十天問的是這個。答案不是「人」兩個字,那太廉價。量出來的是分工:

人做什麼 為什麼只有人能做
造尺 變異體目錄、斷言檢核器、親緣表,每一把都是人設計的,也都有人設計的盲區,出廠時要附
讀原始碼 斷言的兩邊是不是同一段程式算的,只有翻開實作才知道。AI 看不到實作
做決定 規格沒說的事測不出來,只能決定。八十筆決定裡十七筆是這種

AI 補得動的那一格是輸入涵蓋——M09 那條 pytest.raises。窮舉、不嫌煩、不會因為「這種情況不可能發生」就跳過。那正是人最容易偷懶的地方。

至於第一天那個引號。當時的「檢查過」是第二天拆開的三招:只走了一條路、挑了一組會讓缺陷消失的數字、請作者當裁判。三十天後看,那三件事沒有一件叫檢查。驗證的成本沒有跟著產出的成本一起降——這是第一幕量到的第一件事,也是最後一天還在的那件。


後記

修復版的 HTML 是最後一天才寫的,而 Python 版第十五天就有了。中間隔了十五天。

不是拖延。是那十五天在做的事:造尺、量 AI、找沒有答案時的方法——每一天都在確認「修好」這兩個字到底要什麼條件才成立。而且第十五天那版 calc_fixed.py 自己就在圖表餘額上加了一個 max(0.0, b)——跟缺陷 A' 同一個東西,是後來才用 PRD-12 拔掉的。第十五天就接回去,我會得到一支帶著同一塊遮羞布的計算機,跟一年前那支一模一樣。

三十天前那支也「看起來對」。


這些數字不能拿來做什麼

  • v2 只換了計算核心與三處介面手術。表單、圖表元件沒有自動化測試
  • 差分 505 組是抽樣加手選違規,不是窮舉。PRD-04 的其他違規形態(空欄位、非數字字串)在 HTML 層處理,差分看不到
  • 圖表退休當年那一點的語意變了:舊版畫累積期終值,v2 畫第一年提領後的期末餘額。這是 PRD-03 索引對齊決定的,畫面會不同
  • /12 保留是裁決不是修復,代價已明列
  • 「誰來測」那張表是一個受測物、三十天的分工,不是通則
  • 部署與否是閘門 5 的決定。本篇列驗收條件,不替作者按下去

驗收腳本、逐項結果、事前預期在 manifest.yaml 與 verify.sh。


只帶走一件事
「修好了」不是測試全綠。是舊快照紅在預期處、新規格全綠、關係在新舊兩版各得其所、移植跟原本逐位元對齊,四件事同時成立。
少一件,你得到的是一支看起來對的程式。


系列完結。repo:https://github.com/eyelash500/2026_ironman_test_ai/tree/day30


上一篇
【Day30-上】四幕,四個結論,八十筆決定
系列文
AI 寫的測試,誰來測? 共 33 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言