1. 我最先在哪個真實場景撞上這個問題
事情發生在為一個多步驟 Agent 工作流程編寫單元測試的時候。 Agent 需要依序呼叫 MCP 工具、讀取 context 並做條件跳躍。常規的 pytest mock 把每個工具呼叫都替換成固定回值,但測試總是通過,上線後卻頻繁逾時。拖了兩天,才發現問題出在 mock 沒有模擬真實工具的延遲和錯誤反應——而 harness 正是用來解決「測試環境與生產環境差異」的工具。
Harnesses(測試 harness)本質上是一個輕量級的執行框架,它接管 Agent 的輸入輸出,讓你可以在隔離環境中註入 mock 資料、模擬錯誤、記錄行為。但當時我踩的第一個坑是:把 harness 當成普通 mock 用,只替換回傳值,完全忽略了超時、重試和異常流。
2. 做完之後真正改變我判斷方式的幾個結論
在成功用 harness 穩定住測驗之後,我得到了三個關鍵推論:
- Harness 不是萬能膠。它擅長模擬外部依賴,但無法取代碼邏輯本身背鍋。如果你的 Agent 決策邏輯有 bug,harness 只會讓 bug 更快暴露——這是好事,但很多團隊誤以為 harness 能讓脆弱程式碼通過測試。
- Harness 的價值在於「可控的非確定性」。 Agent 的行為往往依賴 LLM 的隨機輸出,harness 可以固定 prompt 和工具輸出,使得每次測試行為可重複。這比單純 mock LLM 端點更徹底,因為它也捕捉了 context 的組裝過程。
- 學習曲線比你想像得陡。 Harnesses 的配置項目很多(timeout、retry、error injection、logging),很容易在配置階段引入新 bug。我最初花了三天時間讓第一個 harness 運行通過,而寫實際測試只用了一天。

3. 當時踩過的坑和後來怎麼修正
最大的坑是過度 harness。當時我想把所有外部呼叫都塞進 harness,包括一個只傳回常數版本的靜態函數。結果 harness 物件變得臃腫,每次測試都加載一堆不必要 mock。修正方法很簡單:只在 harness 中管理真正外部的不穩定依賴(如 LLM 呼叫、第三方 API、檔案系統),純計算邏輯用普通單元測試覆蓋。
第二個坑是忽略 harness 的生命週期。 Harnesses 通常有 setup 和 teardown 階段,我最初沒有在測試之間清理 context,導致多個測試共享同一個 mock 狀態,下游測試被上游的副作用污染。後來在每個測試前後明確呼叫 reset() 才解決。
第三個坑是錯誤模擬不全面。我只模擬了正常回傳和逾時,但漏掉了部分錯誤(如認證失敗、速率限制)。結果上線後 Agent 遇到了 429 錯誤,而 harness 測試從未涵蓋到這種情況。教訓是:用 harness 模擬錯誤時,至少要覆蓋 timeout、HTTP 4xx/5xx 和網路中斷這三種常見異常。

4. 如果你也在做類似工作,最值得先抄寫的一步
最直接的起步動作:用 harness 為你 Agent 中最關鍵的一個外部呼叫(例如唯一一個 LLM API)寫一個「模板 harness」。具體操作是:
- 選擇目前專案中最核心的不穩定依賴(通常是 LLM 或資料庫)。
- 寫一個 harness 類,包含 setup(初始化 mock 伺服器)、execute(呼叫 Agent 並捕獲輸出)、teardown(清理 mock)。
- 在 harness 中固定該呼叫的回應(例如傳回固定 JSON),並記錄實際被呼叫的 prompt 和參數。
- 跑一次測試,確認輸出符合預期。
這一步能讓你半小時內拿到第一個可重複使用的 harness 測試,並立刻發現 prompt 是否被正確拼接、參數是否傳對。我的經驗是,90% 的 prompt 錯誤跑一次 harness 就能暴露。
5. 什麼時候該繼續投入,什麼時候該換路線
繼續投入 harness 的場景:
- 你的 Agent 有 3 個以上的外部依賴。
- 你正在開發新功能,需要確保新程式碼不會破壞已有行為。
- 團隊不斷增加新 agent 或新工具。
該換路線的號誌:
- 你花了超過 2 天仍在調試 harness 配置本身,而不是在寫業務測試。
- 你的外部依賴經常變化,導致 harness 維護工作超過測試收益。
- 專案還處於原型階段,API 和流程每天都在改變。
這些情況下,先用更輕量的 mock 頂住,等穩定性提高後再引入 harness。
寫在最後
Harnesses 不是銀彈,但用對了地方能大幅提升 Agent 工程的測試信心。關鍵在於明確它的適用邊界:控制非確定性、模擬真實失敗、隔離外部依賴。希望這 5 個教訓能讓你少走一些彎路。

暫無評論,快來發表你的看法吧