iT邦幫忙

2026 iThome 鐵人賽

DAY 26
0
AI Engineering

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

【Day25】AI 每個函式都寫對了,湊起來差一個 (1+r)

  • 分享至 

  • xImage
  •  

TL;DR

  • 不知道答案對不對的時候,去找程式裡兩個該吻合的出口,讓它們互相對帳
  • 我寫了四條關係,只有「對帳」那條抓到東西:它揪出上線一年的缺陷 A,而第一幕花了四天驗屍才確認
  • 最有效的那條,剛好是最麻煩、最容易寫錯的那條。明天 AI 會不會挑它?

https://ithelp.ithome.com.tw/upload/images/20260926/20103826hKHdNuhcNV.jpg


前言

昨天的結論是:AI 寫測試時,那個期望值的唯一來源是它自己,而人核不動。所以換個問法:不問答案是多少,只問兩次執行之間該有什麼關係。

明天要把同一份規格交給 AI,要它寫這種測試。但在那之前得先確定一件事:這張考卷本身有沒有鑑別度。

拿一個沒驗證過價值的方法去考 AI,考不出什麼。所以今天先自己寫四條,然後想辦法確認哪一條真的抓得到東西。


四條關係

編號 把輸入怎麼變 輸出該有什麼關係
MR-01 所有金額同乘 k 三個金額輸出剛好也乘 k
MR-02 月存↑/壽命↑/生活費↑/收入↑ 方向固定:不減/不減/不減/不增
MR-03 在月支出與固定年支出之間搬錢,年總額不變 三個輸出逐位元相同
MR-04 資金設成剛好等於目標金額 缺口為 0、期末餘額為 0

四條都不需要知道任何一次的正確答案。

前三條十分鐘寫完。MR-04 花了最久:要先跑一次拿到目標金額,把報酬率和月存歸零好讓累積期退化成恆等式,再餵回去跑第二次。中間任何一步想錯,就會變成一條假的關係。


只有一條抓到東西

判準:把每條關係單獨拿去跑 Day 19 的十四個變異體,看它殺得掉幾個。

  MR-01 線性齊次     0
  MR-02 單調性      0
  MR-03 支出配置不變   0
  MR-04 自我一致性    2   (M01、M11)

最麻煩那條,是唯一抓到東西的。

前三條為什麼落空,事後看得很清楚:它們問的是「這支程式對自己一致嗎」,而它當然一致,bug 也會一致地壞下去。所有金額乘十倍,壞掉的實作照樣等比例地壞;生活費變貴,算錯的目標金額照樣跟著變大。

MR-04 問的是另一件事:這支程式的兩個不同部分,對彼此一致嗎。

(這裡要先講清楚:「殺 0 個」只代表這十四種錯法碰不到那三條關係,不代表它們沒用。如果實作把某個比例運算寫成「加一個固定常數」,MR-01 一秒就抓到,只是我設計的十四個變異體裡剛好沒有那種。這把尺只能證實,不能證偽。)


兩個該吻合的出口

這支程式算的是同一件事的兩面:

  • 目標金額:退休時我需要準備多少錢
  • 餘額軌跡:這些錢夠不夠用到最後

它們在定義上必須對得起來。資金剛好等於目標金額,跑完二十一年就該剩 0,不多不少。

拿這條去跑舊版,也就是那支上線一年的原版:

assert math.isclose(res.balances_raw[-1], 0.0, abs_tol=1e-3)
E  where False = isclose(-28813.50481278846, 0.0, abs_tol=0.001)

差了兩萬八。

去翻實作:

# 目標金額(321–322 行):期末年金折現
target_for_expenses += net / (1 + p.post_retirement_return) ** i

# 餘額軌跡(372 行):期初扣款後滾存
remaining = (remaining - (net_expense + lump_this_year)) * (1 + p.post_retirement_return)

一段假設你年底才花錢,另一段假設你年初就花了。

把折現改成期初再跑一次:

目標金額 期末餘額
現況(期末折現) 328,752.69 −28,813.50
改成期初折現 341,902.79 −0.00

比值 1.040000,精確等於 1 + r_p。那就是 Day 4 推導的同一個因子:「沒有人能等到年底才吃第一頓飯」。

這是缺陷 A。第一幕花了四天驗屍才確認它,Day 6 的五百組差分測試抓不到(影子模型逐行複製原版,兩邊一起錯)。

一條對帳關係,一次就掉出來。而且從頭到尾不需要知道目標金額該是多少。


為什麼這招對 AI 特別有效

因為 AI 是一個函式一個函式寫的。

折現那段單獨看,是標準的年金現值公式,寫得完全正確。提領那段單獨看,是標準的餘額遞迴,也完全正確。兩段各自都對,沒有人要求它們之間要對得起來。

缺口就開在那裡。

這個手法可以直接搬去別的地方,只要找得到「同一份資料的兩個出口」:

情境 該吻合的兩邊
報表 總計 vs 明細加總
API 回傳的 count vs list 長度
對帳單 摘要頁餘額 vs 逐筆交易累加
匯出功能 畫面顯示的筆數 vs CSV 行數

每一組都不需要你知道正確答案,只需要知道它們必須相等。


那個從 Day 20 活到現在的

M14 是「退休後收入不隨通膨調升」,從第一次量變異分數活到今天,沒有任何方法殺得掉。

跑之前我把四條關係逐一推過,寫進預測欄:齊次性抓不到(它改的是通膨指數,不是齊次性)、單調性抓不到(收入增加仍然讓目標金額下降)、支出配置抓不到(那是支出端的事)、自我一致性也抓不到(目標與軌跡用的是同一份壞掉的收入,兩邊仍然自洽)。

實測:四條全部抓不到。

要殺它需要一條關於「通膨率與收入怎麼交互」的關係。那不是套公式套得出來的,得有人真的想過,退休後的收入到底該不該跟著物價走。


後記

四條關係裡我最喜歡 MR-01,最不想寫的是 MR-04。

MR-01 漂亮:一行數學性質,三個 k 值一次驗三個輸出,十行寫完,讀起來像教科書例題。MR-04 醜:繞兩次、設一堆為零的參數好讓公式退化、還得把前一次的輸出接回去當輸入,寫完自己讀都要想一下。

結果漂亮那條什麼都沒抓到,醜的那條抓到了缺陷 A。

這件事對明天很重要。最有效的關係,剛好是最難想到、最麻煩寫的那種,而前面幾天量過 AI 的傾向:它挑好算的數(1000 而不是 19391)、它寫大量看起來合理的弱斷言。它偏好寫起來順、讀起來合理的東西。

所以明天的預測,我先寫在這裡:AI 會寫出前三種那類的關係,寫不出第四種。

猜錯的話,那會是這一幕最值得寫的一天。


這些數字不能拿來做什麼

四條關係是我一個下午寫的,不代表「蛻變關係能做到的上限」。

「殺 0 個」不等於「沒用」,它只說明我設計的那十四種錯法碰不到那三條關係。這把尺只能用來證實一條關係有用,不能用來證明它沒用。原稿的標題本來寫「三條是廢話」,那是把一把已知有盲區的尺當成了真理,被讀者指出來之後改掉。

MR-04 抓到缺陷 A 是單一案例,不構成「對帳關係一定有效」的通則。它證明的是這個方法至少有一次抓到了其他方法漏掉的東西。

逐條結果、事前預測與限制在 manifest.yaml。


只帶走一件事
AI 寫的每個函式可能都是對的,而它們湊不起來。
找出兩個該吻合的出口讓它們對帳:你不必知道正確答案,只需要知道它們必須相等。


明天把同一份規格交給 AI,要它寫這種測試。考卷已經驗過了:四條關係裡有一條真的抓得到東西。

問題是它會不會挑那一條。


今天的 repo:https://github.com/eyelash500/2026_ironman_test_ai/tree/day25


上一篇
【Day24】AI 寫下那個數字的時候,沒有人在旁邊
系列文
AI 寫的測試,誰來測? 共 27 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言