iT邦幫忙

2026 iThome 鐵人賽

DAY 27
0
Vibe Coding

一個 Vibe Coding 專案從原型到有人在用系列 第 27 篇

AI 說「測試到位」的 PR,測試只數了 reload 叫幾次

  • 分享至 

  • xImage
  •  

有人送 PR(把改好的程式送來,請你合併)給你。他附了測試,CI(每次推上去自動跑的檢查)是綠的。AI 審完說:「測試到位,建議合併。」

你不讀 code。這個合併鍵,你按不按?

一個陌生人,送了 27 個 PR

5 月 25 日深夜,一位我不認識的開發者 ericweichun,對 usage(我做的開源小工具,顯示 Claude Code、Codex 這些 AI 工具用了多少額度)一口氣送了 3 個 PR。到 7 月 1 日,他一共送了 27 個。

27 個我全部合併了。每一個都附了測試,說明欄都寫了他跑過的測試指令,CI 全部是綠的。從他送出到我合併,最快 2 分鐘;27 個裡有一半,不到 3 小時 42 分。

這個系列講過他好幾次。Day 1 開場那個錯,是他修好的:usage 把一天 38.74 美元的 Codex 花費,算成 465.22 美元。Day 9 那個測試也是他送的:把他的修正拿掉,測試照樣綠(通過),等於沒碰到那個 bug。Day 26 那條會自己叫 reload()(重新載入)的程式,同樣來自他的 PR #29。

我不逐行讀 AI 寫的 code,改動對不對,要靠 code 以外的方法確認,這是 Day 1 講過的系列前提。這 27 個 PR,我是怎麼決定收的?

兩個 PR,AI 都說「測試到位」

前 10 個 PR,有 5 個在 GitHub 上被要求改過才合併。之後的 17 個,GitHub 上我沒有再留過一則審查。27 個裡,有 19 個從頭到尾沒有任何留言。

後來的審查,是 Claude Code 在我們的對話裡做的。有幾次,它的回報寫著它在我的電腦上跑完了全部測試;也有幾次,回報裡只寫了改動範圍和 CI 結果。

PR #29 修的是面板突然變空白:負責畫面板的那個程式偶爾會自己掛掉,面板就變成一片空白或灰色,要重開 App 才會好。他的修法是偵測到掛掉,就把面板重新載入。6 月 6 日下午,Claude Code 看完這個 PR,結論是:問題真實、改動乾淨、測試到位、CI 過。兩分鐘後,PR 合併。

6 月 18 日,它看的是 PR #40,就是修好 465.22 美元那個錯的 PR。它的結論也有一句「測試到位」:新增 3 個測試,涵蓋三種情況,CI 綠燈。兩分鐘後,PR 合併。

兩次都是「測試到位」。可是 Day 26 看過了,#29 的測試只數了 reload() 被叫幾次。

拿掉修正,兩個 PR 的測試都會紅

Day 9 教過一招:把修正拿掉,測試留著,跑一次。會紅(測試失敗),測試才碰得到那個 bug。寫這篇時,我把兩個 PR 都這樣跑了一次。

#29:把 reload() 那一行換成什麼都不做,它的兩個測試都紅了。

#40 改了兩個程式檔、兩個測試檔。我把兩個程式檔換回修正前,測試檔留著,跑這兩個測試檔裡的 45 個測試:紅了 40 個,其中 39 個是同一種錯誤。

Day 9 那篇還有後半句:紅的原因要是那個 bug,不是打錯字、少了檔案。這 39 個錯誤,全是同一句 AttributeError。測試開跑前有一步準備:清空一個暫存區。這個暫存區是 #40 才加進程式的,舊程式沒有,準備這一步就出錯,測試根本還沒開始檢查。這種紅,跟算錯錢無關。

我在舊程式裡補上一個空的暫存區,再跑一次。這一行只讓準備步驟跑得動,不改任何計算,舊程式算用量的方法還是錯的那套。這次 7 個測試紅了,紅的都是算出來的用量數字和筆數。放回修正,45 個全過。

所以兩個 PR 都過了「拿掉修正會紅」這一關。只做這一半,分不出它們。

紅在哪一行:使用者看到的數字,還是程式的一個動作

分得出來的,是後半句:紅的時候說了什麼。測試失敗時,會印出沒對上的那一行。assert 是測試裡的檢查句,左邊是程式實際算出來的,右邊是應該要有的。兩個 PR 各挑一行:

#40:assert 7 == 3
#29:assert 0 == 1

#40 那行,翻成白話是:輸出用量應該是 3,舊程式算成 7。Codex 的紀錄裡,輸出的數字已經包含推理(AI 回答前先想的那一段)。測試資料寫的是輸出 3、推理 4,舊程式把推理又加了一次。Day 1 那個 12 倍,有一部分就是這樣來的。使用者在面板上看到的花費,就跟著偏高。

#29 那行,翻成白話是:reload() 應該被叫 1 次,結果 0 次。面板最後有沒有回來,它沒說。

#29 的測試沒有用真的網頁元件,用的是測試自己寫的假元件。假元件的 reload() 什麼都不做,只把次數加 1。測試的名字寫著「畫面程式停止之後,重新載入並補回資料」,內容卻沒有讓畫面程式停止,是直接叫 PR 新加的那段重新載入程式,再看次數。

https://ithelp.ithome.com.tw/upload/images/20261011/20183178ZzwHNFyJIi.png

今天把 Day 9 那句的「那個 bug」說得更具體:是使用者看到的症狀。#40 紅在使用者會看到的數字上;#29 紅在修法自己的一個動作上,修法有沒有被執行,跟使用者看到什麼,是兩件事。

不讀 code,叫 AI 分出測試在看什麼

這兩行白話,我也是請 AI 翻的。寫這篇時,我把同一段提示詞分別交給 Codex,各看一個 PR,沒告訴它哪個好、哪個壞。我是用合併的 commit 指給它看;你可以換成 PR 網址,或叫它先跑 gh pr diff 編號:

我不讀程式碼。請幫我看這個 PR 新加或改過的每一個測試:
1. 用一句白話說:這個測試最後檢查的是什麼?
2. 分類:A=使用者會看到的結果(畫面上的字、算出來的數字或清單、寫出來的檔案內容);B=程式內部有沒有做某個動作(某個函式被叫了幾次、某個旗標有沒有設、用假物件代替真的元件)。
3. 如果是 B:這個 PR 想修的問題,使用者看到的症狀是什麼?測試要怎麼改,才會直接檢查那個症狀?

最後一行寫:「這個 PR 的測試,有沒有檢查到使用者看到的症狀:有/沒有/部分」。

#40 新增 3 個、改了 4 個,共 7 個測試,它全判 A,最後一行寫「有」。#29 的 2 個測試,它全判 B,最後一行寫「沒有」。#40 的測試其實也用了假的資料檔,它還是判 A:看的是測試最後檢查什麼,不是用了什麼假東西。對 #29,它也給了改法:用真的面板先顯示「Codex 用量 67%」,讓畫面程式停止,等面板重新載入後,檢查畫面上還看得到 67%。

6 月那兩次審查的回報裡,寫的是測試有沒有、過了沒、涵蓋哪幾種情況,沒有一句說測試最後看的是什麼。這段提示詞問的就是這一件事。

這段提示詞,兩個 PR 我各只問了一次,AI 的分類也可能錯。它判成 B 的,照第 3 點補一個測試,再用 Day 9 的方法拿掉修正跑一次,看它紅在哪一行。

PR 說明的打勾清單,有沒有寫前後數字

不看測試,也有線索。27 個 PR 的說明欄,都有一份打勾的清單。

#40 的清單裡,有一格寫的是真實資料的前後數字:

Real-data verification: today's total dropped from the false $465.22 to $38.74

修正前多少、修正後多少,都寫出來了。

#29 的清單也勾了一格手動驗證:他重現了面板不見的狀態,裝上這個修法,重開 App。修好之後面板有沒有回來,這一格沒寫。

27 個 PR 裡,說明欄附了修正前後數字的,只有 2 個:#40,還有他另一個把 usage 的 CPU 用量從約 60% 降到 0.0% 的 PR #41。

今天可以帶走的

工作單(交給 AI 的任務說明)裡那格「做完怎麼算對」,今天再加兩行(沒用過這張工作單,也可以直接把這兩行交給 AI,當作驗收要求):

做完怎麼算對:
- (Day 4、Day 8 到 Day 26 加的幾行)
- 新加或改過的測試:每一個用一句白話說它最後檢查什麼,標出是「使用者看得到的結果」還是「程式內部有沒有做某個動作」。修 bug 的測試至少要有一個是前者,Day 9 那條「拿掉修正要紅」就拿這一個來跑
- 收別人或另一個 AI 送來的改動:說明裡要貼修正前、修正後各一次的實際結果(數字、畫面截圖或輸出);只勾「手動驗證過」,不算數

如果你的專案收別人的 PR,把貼前後結果那一行放進 PR 範本:

- [ ] 修正前、修正後,使用者看到的結果各貼一次

Day 22 到今天:使用者走的路,我沒走過

這篇是上線段的最後一篇。Day 22 到今天這六篇,出事的地方都在同一種位置:使用者走的那條路,我自己平常不走。

第一個陌生人下載的是打包好的 App,我每天跑的是專案資料夾裡的原始碼(Day 22、Day 23)。App 的提示叫人打指令,可是看到提示的人裝的是 App,提示叫他跑的那個 main.py,在 App 裡不能直接跑(Day 24)。README 那行 brew 安裝指令,CI 和發版流程沒有一步照著跑過(Day 25)。面板的右鍵選單是系統送的,我沒寫過,也沒有一個測試碰過它(Day 26)。今天的測試也一樣:它從程式裡面看 reload() 叫了沒,使用者從畫面外面看面板回來了沒。

https://ithelp.ithome.com.tw/upload/images/20261011/20183178nFSTjPY9hw.png

Day 1 的路線圖分成五段:下指令、驗收、品質、上線、收尾。上線這一段到今天結束。明天開始最後一段:把前 27 天整理成能直接套用的東西。先把 Day 2 到 Day 7 講的那張工作單拿出來,用它把 Day 26 的 #42 重修一次。

參考資料

  • usage 專案:https://github.com/aqua5230/usage
  • ericweichun 送的 PR(全部合併):https://github.com/aqua5230/usage/pulls?q=is%3Apr+author%3Aericweichun
  • PR #29〈fix: reload web panel after render process failures〉:https://github.com/aqua5230/usage/pull/29
  • PR #40〈fix: correct Codex fork and reasoning usage accounting〉:https://github.com/aqua5230/usage/pull/40
  • PR #41〈fix: reduce menu bar energy use during Codex activity〉:https://github.com/aqua5230/usage/pull/41

上一篇
我沒寫過的 Reload,讓面板一片空白
系列文
一個 Vibe Coding 專案從原型到有人在用 共 27 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言