iT邦幫忙

2026 iThome 鐵人賽

DAY 20
0
ChatGPT & Codex

挑戰 30 天把 ChatGPT 與 Codex 放進軟體開發流程系列 第 20

Day 20|自動化測試維運:先證明根因,再處理紅燈

  • 分享至 

  • xImage
  •  

Day 20 封面:先證明根因,再處理紅燈

Day 19 的 08:00 與 07:59 測試鎖住舊發送規則;今天驗證「發送前一小時開始製作」,邊界因此移到 07:00。我尚未接上真正的持續整合(Continuous Integration,CI),而是在本機注入世界協調時間(Coordinated Universal Time,UTC)的固定時鐘模擬執行器。結果 startsOneHourBeforeSendTimeInTheReportZone 出現 expected: <true> but was: <false>

紅燈先分流,不先改斷言

我把 log 切成三段看:Maven 是否完成解析與編譯、Maven Surefire 測試外掛是否真的啟動 JUnit、哪個案例在哪種環境失敗。這次前兩段都正常,差異集中在 UTC 與臺北時間。若此時直接把 assertTrue 改掉,07:00 沒有開始製作報表的錯誤也會一起被放過。

類型 我會找的證據 可接受處理
產品缺陷 固定輸入仍穩定失敗 最小修改並補回歸測試
測試缺陷 斷言與需求或公開介面不符 修正測試意圖
環境差異 Java 開發工具包(Java Development Kit,JDK)、時區或設定不同 固定並記錄環境
相依問題 測試啟動前解析失敗 核對來源、版本與權限
偶發失敗 相同條件下結果不一致 找共享狀態、時間或競態

持續整合紅燈的五類分流與禁止捷徑

先讓 Codex 診斷,暫時不給修正權

我把去除帳號、路徑與憑證的失敗摘要、pom.xml、正式程式與測試交給 Codex,並把順序寫清楚:

先不要改檔。重現指定測試,列出三個根因假設與驗證順序。
證據足夠後,只能修改 ReportProductionWindow 與對應測試。
禁止刪除測試、放寬斷言、無條件重試或順手重構。
最後執行局部測試、完整測試,回報命令與殘留風險。

這個邊界讓 Codex 先比對時間值。失敗版本雖然收到了 reportZone,卻只呼叫 ZonedDateTime.now(clock);測試注入 UTC 的固定 Clock 時,程式直接拿 23:00 與預期的臺北 07:00 比較。根因是產品程式忽略訂閱時區,誤用注入時鐘的 UTC 本地時間,不是 JUnit 5 判錯。

排除順序留在診斷任務:Surefire 報告已有測試名稱與堆疊,表示建置與 JUnit 都已啟動;固定瞬間排除等待造成的不穩;逐項比對 Clock 時區、訂閱時區與預期時間後,才定位到未使用的參數。

從失敗訊息、假設到最小重現的診斷順序

回歸測試固定瞬間,也明確指定業務時區

我用 Clock.fixed() 在本機固定 UTC 瞬間,再明確傳入業務時區 Asia/Taipei

Clock ciClock = Clock.fixed(
        Instant.parse("2026-08-18T23:00:00Z"), ZoneOffset.UTC);
ReportProductionWindow window = new ReportProductionWindow(ciClock);

assertTrue(window.shouldStart(
        LocalTime.of(8, 0), ZoneId.of("Asia/Taipei")));

我用同一個測試類別放入三個固定瞬間:23:00Z 轉成臺北 07:00 時必須啟動;22:59Z 與 23:01Z 轉成 06:59 與 07:01 時都必須保持關閉。withZoneSameInstant(reportZone) 加入前,第一條斷言固定出現 false;加入後三條一起通過。前後各一分鐘的測試也能攔住「07 點整個小時都啟動」的錯誤實作。完整內容可看 ReportProductionWindowTest.java

時區缺陷修正前後與三條邊界測試

綠燈要附上可重跑的證據

修正前,指定類別是 3 項測試、1 項失敗;修正後重跑指定類別與 mvn clean test,兩次都是 3 項通過、BUILD SUCCESS。這只證明注入 UTC 時鐘、以臺北為業務時區的縮小案例正確,尚未證明真正的 CI、正式排程器、產製耗時與郵件送達。命令與限制記在驗證紀錄。日後若使用 CI log,我會先移除儲存庫名稱、內部路徑、Token 與服務網址。

修正前失敗、局部測試與乾淨建置三段證據

小結:先證明根因,再讓測試變綠

這次我要求 Codex 交出的不是一句「已修好」,而是失敗命令、時間換算、程式差異與重跑結果。這些資料讓我能逐項判斷是否放行,也留下日後再次失敗時的比較基準。Day 21 會帶著這份基準進入陌生的遺留程式碼(Legacy Code),從可觀察行為畫出程式路徑。

參考資料


上一篇
Day 19|大型重構任務拆解:讓每次改動都能停、能測、能退
下一篇
Day 21|遺留程式碼考古:每個理解都要能回到證據
系列文
挑戰 30 天把 ChatGPT 與 Codex 放進軟體開發流程21
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言