iT邦幫忙

2026 iThome 鐵人賽

DAY 28
0
Vibe Coding

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

照工作單把舊 bug 重修一次,才發現 Reload 從沒被拿掉

  • 分享至 

  • xImage
  •  

你修好一個 bug:測試綠了,AI 回報「入口已被移除」,你回覆使用者「修好了」,他也沒再回來。

這個 bug,真的修好了嗎?

收尾第一篇:拿工作單重修一個舊 bug

Day 1 的路線圖分五段:下指令、驗收、品質、上線、收尾。今天開始最後一段,收尾。

Day 2 到 Day 7 講的是怎麼對 AI 下指令,最後收成一張工作單(交給 AI 的任務說明,分成改哪裡、哪裡不准動、做完怎麼算對等幾格,完整的一張放在文末)。之後每一篇,又往「做完怎麼算對」那一格加了幾行。今天不重講這些格子,直接拿來用:挑一個真的 bug,用這張工作單重修一次,看它會不會多抓到什麼。

挑的是 Day 26 的 #42:使用者在 usage(我做的開源小工具,顯示 Claude Code、Codex 這些 AI 工具用了多少額度)的面板(點選單列圖示彈出的視窗,裡面是一頁網頁)上按右鍵、點 Reload,面板變成一片空白。6 月 22 日當晚就修了,v0.22.5 發出。

同一個 bug,兩張單

我用 git 把 usage 退回 6 月 22 日修正之前的版本,開兩份一樣的資料夾,交給同一個 AI(Codex)各修一次。

  • A 單:6 月 22 日當晚真正交出去的那張任務書,一字不改。它寫了目標、根因、要改哪兩個檔、不准動哪裡。驗收寫的是:格式檢查、型別檢查、測試全綠,再做一次「邏輯檢查」,確認使用者右鍵點 Reload 的路徑已被堵住。
  • B 單:目標、根因、要改的地方一字不改。驗收和其他幾格,換成 Day 2 到 Day 25 的格子。

B 單多出來的格子是這幾個:

症狀怎麼量:在面板上右鍵點 Reload 之後,量面板畫面上的文字;
          修完再量同一個地方,貼出前後的畫面文字;
          你量不到的話,說你量不到,交回來給我量;不要改量別的(Day 6)
哪裡不准動:每一條附上原因(Day 3)
已經決定的:右鍵選單保留「複製」,因為使用者會複製面板上的數字(Day 7)
做完怎麼算對:
- 拿掉修正要紅,紅在「面板畫面上的文字變成空的」(Day 9)
- 修正改了幾處,每一處分開拿掉、各跑一次(Day 23)
- 照使用者寫的步驟重跑一次,貼出成功的輸出(Day 25)
- 驗不到的:先說哪一類你驗不到,再列出這次落在裡面的項目(Day 4)
停損:同一處改超過 3 次還是不過,就停(Day 5)
你自己決定的:工作單沒寫、你自己拿主意的地方,全部列出來(Day 7)

Day 26、Day 27 加的那幾行,我刻意沒放。那兩篇就是從 #42 學來的,放進去等於先給答案。

A 單交回修正,B 單交回一張待驗清單

A 改了兩個檔,新增了右鍵選單的測試,相關的 5 個測試都過。全套測試在 AI 的執行環境裡跑到一半中止,那個環境開不了視窗。它的回報最後老實寫了一句:本環境不能驗證真實右鍵選單及視窗重繪。

B 一行程式都沒改,觸發了停損(工作單裡寫好的「做不下去就停」條件)。6 月 22 日那張單本來就寫著一條:WKMenuItemIdentifierReload 拿不到,就停手回報;兩張單都有這一條。它的回報說,任務書要它找選單項目的 itemIdentifier,可是 Mac 的選單項目沒有這個方法,只有 identifier;實際的右鍵選單會給什麼值,它沒辦法證實。它也開不了視窗,量不到畫面上的字。這裡的「量」,是讀出面板畫面上實際顯示的文字。

所以它把量不到的四件事交回給我:

  • 修正前:在面板右鍵點 Reload,記錄面板畫面顯示的文字。
  • 修正後:確認右鍵選單沒有 Reload/上一頁/下一頁/開新視窗。
  • 修正後:選取面板數字,點「複製」,確認剪貼簿內容。
  • 修正後:驗證重載與畫面程式崩潰後,面板恢復原本內容。

回報裡還有一句:「未改量假 view、HTML 原始碼或其他文字來冒充畫面結果。」這是 Day 6 那一格的作用:量不到,就交回來,不要改量別的。

方法名稱不對,A 其實也發現了。它的回報開頭寫著:「NSMenuItem 沒有 itemIdentifier(),但提供 identifier()。」它改用 identifier,找到別的路繼續寫下去;同一條停損,A 沒有停。兩張單各只跑一次,這不能證明哪張單比較好。可是 B 交回來的那張清單,我拿去檢查了已經上線的版本。

https://ithelp.ithome.com.tw/upload/images/20261012/20183178BWfrjEJmvP.png

照 B 的清單,在真的面板上按一次右鍵

清單的第二項,就是 Day 26 加進「做完怎麼算對」的那一行:「對每個畫面按右鍵、把選單每一項點一次……程式自己會重新載入畫面的地方,要在真的網頁元件上跑一次。」

我寫了一支小程式,開一個真的視窗,放進 usage 自己的面板,送一次右鍵,在選單打開前印出每一項;接著點 Reload,再讀面板上的字數。跑的是 v0.22.5 之後一直沒變的那段過濾程式(輸出只留字數):

送資料之後:字數 323
usage 過濾後的右鍵選單:['Reload', '']
點 Reload 之後:字數 0
再送一樣的資料:字數 0
送不一樣的資料:字數 323

Reload 還在。點下去,面板空了。

6 月 22 日的修正,從來沒有拿掉 Reload。這段過濾程式從那天起一行沒改,所以從 v0.22.5 到寫這篇時的 v0.33.2,139 個版本都是這樣。

面板會回來,是靠同一天改的另一處:程式要重新載入時,把原本的 HTML 再交一次。可是 usage 送資料前會先比對,資料跟上次一樣就不送。所以使用者按了 Reload 之後,面板會一直空著,等到送進面板的資料有變化,才回來。

https://ithelp.ithome.com.tw/upload/images/20261012/20183178JFtoQCg5C5.png

問題出在一個方法名稱

修正明明寫了要拿掉 Reload,為什麼沒拿掉?6 月 22 日的過濾程式,是這樣讀選單項目的:

item_identifier = getattr(item, "itemIdentifier", None)

真的右鍵選單裡,每一項是 Mac 一般的選單項目。系統把選單顯示出來之前,會先通知 App 一次;我在這時把每一項印出來:

'Reload' | class: NSMenuItem | respondsTo itemIdentifier: False | identifier(): WKMenuItemIdentifierReload

沒有 itemIdentifier 這個方法,識別碼放在 identifier。程式讀不到,就當作「不是要拿掉的項目」,一項都沒拿掉。

那測試為什麼是綠的?因為測試用的選單項目是假的,假物件自己寫了一個 itemIdentifier:

class FakeMenuItem:  # 節錄
    def itemIdentifier(self) -> str | None:
        return self.identifier

方法名稱是哪裡來的?6 月 22 日那張任務書的「預期行為」(寫改完應該怎樣的那一格)裡,有一句實作建議:移除 itemIdentifier() 含 Reload 的項目。這個名稱沒有人在真的選單上查過。同一張單的根因那格,還標著「已查清,照此修,勿重新發明」。修的 AI 照著寫,假物件照著寫,測試拿假物件證明自己對。

Day 6 那格寫的是:猜的就寫「猜的」,附上證據指到哪。Day 26、Day 27 講的是:只用假物件驗,不算數。這一次兩個都踩到了:方法名稱是猜的,沒標「猜的」;測試又只拿照著猜寫出來的假物件來驗。

修法:改一個名稱,測試改用真的選單項目

寫這篇時,我在 usage 開了一個分支修它。程式只改一個名稱:itemIdentifier 換成 identifier。測試不再用假物件,改用 Mac 真的選單項目:

item = NSMenuItem.alloc().initWithTitle_action_keyEquivalent_("", None, "")
item.setIdentifier_("WKMenuItemIdentifierReload")

先只改測試、不改程式,跑一次,紅了(測試失敗):

At index 0 diff: 'WKMenuItemIdentifierReload' != 'WKMenuItemIdentifierCopy'

翻成白話:過濾完,選單第一項還是 Reload。這就是使用者按右鍵會看到的:Reload 還在。改了程式再跑,綠了。CI 在 Mac 上跑的七項檢查,在本機全跑一遍,全過。最後用同一支小程式在真的面板上按右鍵(輸出整理過):

usage 過濾後的右鍵選單:['']
選單裡沒有 Reload 可點;面板字數:323

Reload 不見了,面板還在。

你也可以印一次自己的右鍵選單

你的 App 如果有網頁畫面,可以叫 AI 寫一支同樣的小程式:開一個真的視窗,在右鍵選單打開前,把每一項的名稱和識別碼印出來。Mac 的 WKWebView(App 裡顯示網頁的元件)會在選單打開前呼叫 willOpenMenu_withEvent_,在裡面印 item.title() 和 item.identifier() 就行。

重點不在印出來的內容,在「真的」兩個字。過濾程式的測試,至少要有一個是拿真的選單項目跑的;假物件長什麼樣,是寫測試的人決定的,真的選單長什麼樣,是系統決定的。

今天可以帶走的

工作單的完整格子,是 Day 7 那張加上 Day 6 的「症狀怎麼量」;「做完怎麼算對」累積的行,明天分組列出:

改哪裡:___(猜的就寫「猜的」,附上證據指到哪)(Day 2、Day 6)
症狀怎麼量:在___量到___,正常應該是___;修完再量同一個地方,貼出前後;
          量不到就說量不到,交回來給我量,不要改量別的(Day 6)
哪裡不准動:___,因為動了會___壞掉(Day 3)
已經決定的(不要自己改):___,因為___(Day 7)
做完怎麼算對:
- 你自己驗:___(跑了什麼、結果是什麼貼在回報裡)(Day 4)
- 我自己按:打開___,按___,應該看到___(Day 4)
- 驗不到的:先說哪一類你驗不到,再列出這次落在裡面的項目(Day 4)
- (Day 8 到 Day 27 加的幾行,明天照情境分組)
停損:同一處改超過 3 次,檢查還是不過,就停,回報卡在哪(Day 5)
你自己決定的:工作單沒寫、你自己拿主意的地方,全部列出來(Day 7)

「做完怎麼算對」今天再加一行:

- AI 交回來的「驗不到的」:每一項寫上誰來做、做完貼什麼;沒人做完,就不准回覆使用者「修好了」

6 月 22 日當天,AI 只回報「入口已被移除」,驗不到的那一項「在真的面板上按右鍵」沒被列出來。當天只要有人在真的面板上按過一次,就會看到 Reload 還在。今天 A 重跑同一張單,倒是寫了驗不到;可是那張單沒有一格要人接手。

明天,把 Day 4、Day 8 到今天加進「做完怎麼算對」的每一行,照情境分組,排成一張清單;再拿今天這個修正,照清單從頭驗一次。

參考資料


上一篇
AI 說「測試到位」的 PR,測試只數了 reload 叫幾次
下一篇
測試全綠的一行修正,清單說還不能回覆「修好了」
系列文
一個 Vibe Coding 專案從原型到有人在用 共 31 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言