工商時間TDD、E2E、自動化驗證——課程裡每個功能都是這樣長出來的,不是先寫完再祈禱。 《AI 賦能全端開發:從零打造企業級智慧應用》:用同一套 AI CRM 專案,從 Spring Boot 後端、React 前端到資料庫與權限,一路加上 Spring AI、RAG 與 AI Agent,完成真正能上線的企業級應用。 |
主題一|開發驗收期:測試不是驗證工具,是規格文件——可審查產物系列・站 3
嗨,我是凱文大叔。
上期結尾埋了一個伏筆:設計期那批「可打勾」的驗收標準,會一模一樣地出現在測試名稱裡。這期兌現。第三站:開發驗收期——全系列份量最大的一站,因為它有三層。
一句話換成三層
❌「幫我測試程式有沒有問題」——這句話的問題是,它把測試當成一個事後的動作。
但測試不該是事後的。它應該從開發第一分鐘就開始,而且結束時要留下三樣東西:
- 開發時就 TDD:先寫測試 → 紅 → 實作到綠 → 重構
- 完工後 Playwright E2E:寫成可重跑的腳本檔
- E2E 每步截圖 → 用這批圖產出 SOP 操作手冊
一層一層來。
3-1 開發時就 TDD:先讓我看到紅燈
為什麼要它「先寫測試」?因為 AI 寫完程式再補測試,它會寫出證明自己對的測試。測試變成實作的鏡子——你拿它驗證,等於拿它自己驗證它自己。
先寫測試,測試就是規格。
提示詞全文(可直接複製)
用 TDD 實作【功能】:
1. 先寫測試,跑一次,讓我看到它是紅的(失敗訊息貼給我)
2. 再寫最小實作讓測試轉綠
3. 最後重構,重構後測試必須維持綠
測試要涵蓋:正常路徑、邊界值、錯誤分支。
在我確認紅燈之前,不要寫實作程式碼。
最後一句約束不能少:「在我確認紅燈之前,不要寫實作程式碼。」沒有這句,它會一口氣寫完,然後告訴你「測試都過了」——你既沒看到紅燈,也不知道測試到底驗了什麼。
紅燈長這樣:

注意失敗原因:not implemented——是功能未實作,不是打錯字。這件事要確認,否則你紅得沒有意義。紅燈證明測試真的在驗證(不是永遠會過),綠燈才證明實作滿足規格。
然後是綠燈——這是整場直播我最喜歡的一張:

到這裡我沒有給你們看過任何一行程式碼。但你現在已經知道這個系統的所有規則了:前置任務未完成時,任務對外顯示為 BLOCKED;同優先級同建立時間時,ID 較小者優先;被阻塞的任務不會被建議。
這就是先寫測試的真正價值——測試不是驗證工具,是規格文件。而且對照上期:這些測試名稱,正是設計期那批驗收標準的一比一翻譯。
3-2 完工後 E2E:腳本是資產
單元測試驗的是規則,E2E 驗的是「使用者真的能走完流程」。這裡有一個很容易忽略的要求:
提示詞全文(可直接複製)
用 Playwright 幫我寫 e2e 測試腳本,涵蓋這幾條使用者流程:
【流程 1】【流程 2】【流程 3】
要求:
- 寫成可重跑的腳本檔,放在 e2e/ 目錄下,加中文註解說明用途
- 不要用一次性的互動指令
- 每個腳本可獨立執行,失敗時輸出足以定位問題的訊息
重點是那兩句:「寫成可重跑的腳本檔」「不要用一次性的互動指令」。AI 很喜歡當場開瀏覽器幫你點一遍,然後跟你說「測過了,沒問題」——那個「測過」跑完就蒸發了,下次改了程式又要重來。
一次性指令跑完就沒了。腳本是資產。
之後每次改完程式,一行 npx playwright test,它自己開瀏覽器、自己填欄位、自己點按鈕、自己驗證結果。
3-3 最划算的一招:讓測試自己長出操作手冊
到這裡都還算正常。接下來這一招,是我覺得整場最划算的。
E2E 反正每一步都在操作畫面——那就順手把每一步截圖存下來:

然後:
提示詞全文(可直接複製)
在 e2e 腳本的每個關鍵步驟後加上截圖,存到 e2e/screenshots/ 並依步驟編號命名。
跑完後,用這批截圖幫我產出一份操作 SOP 文件:
每個步驟一張圖 + 操作說明 + 預期結果 + 常見錯誤。
輸出成 Markdown。
同一次執行,兩份產物:一份給機器看(回歸測試),一份給人看(SOP 操作手冊)。

沒有人手寫這份文件。它是測試跑完自己長出來的。而且它永遠跟程式同步——因為它是從實際跑過的畫面生出來的。流程改了、測試會跟著改,SOP 下次重跑就自動更新。
你有多少份文件,是寫完那天就開始過期的?
站 3 收工
開發驗收期的換句話練習:一句「幫我測試」換成三層產物——TDD 讓測試先於實作(規格不是鏡子)、E2E 腳本是可重跑的資產、截圖生 SOP 讓文件永遠跟程式同步。
下期是系列完結篇:上線前。「幫我看看有沒有資安漏洞」這句話缺了什麼?為什麼全綠的稽核報告反而可疑?還有一句誠實話:AI 稽核取代不了什麼。最後把四站收成一張你可以直接存下來的總表。下期見。
主題二|事件送得出去:交易邊界與 Outbox
上期把 AI 摘要丟到背景執行緒,存檔變快了。這期要講一個在那之後才會浮現的問題。
先看這段程式——它有一個 bug,但你可能看了三遍都找不出來:
@Transactional
public void updateCustomer(Long id, CustomerForm form) {
Customer customer = repository.findById(id).orElseThrow();
customer.apply(form);
publisher.publishEvent(new CustomerUpdated(customer.getId()));
}
問題是:publishEvent 這一行執行的時候,交易還沒有 commit。
@Transactional 的 commit 發生在方法返回之後。所以事件送出去的那一刻,客戶資料還只存在於這個交易裡,資料庫外面的世界看不到它。
平常這沒事,因為交易通常都會成功。但只要有一次沒成功——
一次 rollback 就穿幫
我實際跑了一次:讓交易在 publishEvent 之後拋例外、rollback,然後看監聽器有沒有跑。
T1 交易 rollback 後,一般 @EventListener 竟然已經執行過了
監聽器執行=true / 資料庫實際內容=原本的名字
監聽器執行了。資料庫裡卻還是「原本的名字」——那筆更新根本沒存進去。
上期我們已經讓摘要在背景執行緒跑了,所以這裡發生的是:AI 對著一筆根本不存在的更新,認真地產生了一份摘要,然後把它存起來。
使用者看到的畫面是:客戶資料沒變(存檔失敗了),但摘要換成了新的、描述著一個從未存在過的版本。
這種 bug 最麻煩的地方在於——它平常不會出現。你的測試會過、開發環境會過、上線頭三個月都不會有事。它只在 rollback 的那一次出手,而那通常發生在半夜、發生在你查不到的地方。

