測試案例生成
使用 Claude 生成完整的測試套件 — 單元測試、整合測試、邊界案例和測試數據。
你將學到什麼
- 如何提示 Claude 生成不只涵蓋正常路徑,還涵蓋邊界情況和錯誤條件的單元測試
- 生成整合測試、測試數據固定裝置和基於屬性的測試案例的技巧
- 如何使用 Claude 審核你現有的測試套件以找出覆蓋差距
使用情境
撰寫測試是軟體開發中最有價值但也最耗時的部分之一。大多數開發者知道他們應該寫更多測試——瓶頸不是意圖,而是時間。思考每個邊界情況、撰寫測試框架、生成真實的測試數據,以及在程式碼改變時維護測試都需要大量精力。Claude 可以大幅加速這項工作。
關鍵洞見是測試生成是 Claude 特別擅長的事情,因為它需要系統地列舉案例——Claude 比處於心流狀態的人類做得更好。當你可能為顯而易見的輸入撰寫測試並稱之為完成時,Claude 會有條理地思考:如果輸入是空的怎麼辦?如果它在限制條件的邊界怎麼辦?如果依賴返回意外的類型怎麼辦?如果兩個有效的輸入以令人驚訝的方式交互怎麼辦?
這適用於各種測試類型。對於單元測試,Claude 撰寫圍繞單一函數的專注斷言。對於整合測試,Claude 可以生成針對你 API 的完整請求/回應循環。對於測試數據,Claude 創建帶有實體之間正確關係的真實固定裝置。對於基於屬性的測試,Claude 可以描述你的程式碼應該始終滿足的不變量。
逐步指南
第一步:提供測試對象的程式碼和你的測試框架
始終先指定:
- 你使用的測試函式庫/框架(Jest、pytest、Go testing、JUnit、RSpec 等)
- 任何模擬函式庫(Jest mocks、unittest.mock、sinon 等)
- 你想測試的程式碼(貼上完整的函數或類別)
Claude 需要知道框架才能生成語法正確的測試並使用正確的斷言 API。
第二步:請求跨類別的系統性覆蓋
不要只請求「一些測試」。請 Claude 涵蓋具體的類別:
- 正常路徑 — 具有正確預期輸出的標準有效輸入
- 邊界條件 — 在有效範圍邊緣的值(0、-1、最大整數、空字符串、單個元素等)
- 無效輸入 — null/undefined、錯誤類型、超出範圍的值
- 錯誤條件 — 當依賴失敗、網路不可用等時發生什麼
- 並發或時序 — 如果適用
組織你的提示:「撰寫涵蓋以下的單元測試:(1) 正常使用,(2) 邊界值,(3) 應該拋出錯誤的無效輸入,(4) 外部依賴返回錯誤的案例。」
第三步:請求真實的測試數據
佔位符測試數據(name: "test"、id: 1)產生可能無法捕捉真實世界失敗的脆弱測試。請 Claude 提供真實看起來的數據:
「使用真實看起來的測試數據——真實看起來的姓名、有效的電子郵件格式、真實的美元金額、實際的 ISO 日期字符串。」
對於帶有關係的複雜實體圖,描述關係並請 Claude 生成滿足所有外鍵約束和業務規則的固定裝置數據。
第四步:請求記錄意圖的測試描述
好的測試名稱和描述就是文件。請 Claude 撰寫描述場景和預期結果的測試名稱,而不只是被測試的函數:
- 弱:
test_process_payment() - 強:
test_process_payment_raises_InsufficientFunds_when_balance_is_below_amount()
在你的提示中添加:「命名每個測試以描述被測試的場景和預期的結果。遵循模式:test_[函數]_[場景]_[預期]。」
第五步:審核現有測試以找出差距
貼上你現有的測試文件和它所測試的程式碼,然後問:
「根據程式碼審查這些現有測試。目前未涵蓋哪些案例?列出缺少的測試場景,然後撰寫缺少的測試。」
這是 Claude 在測試方面最有效率的用途之一——它同時閱讀生產程式碼和測試程式碼,並識別增量差異。
提示範本
框架:[pytest / Jest / Go testing / JUnit / 等]
模擬函式庫:[unittest.mock / jest.fn() / sinon / 等——或「不需要」]
以下是我想測試的函數/類別:
[貼上測試對象的程式碼]
請撰寫涵蓋以下的全面測試:
1. 具有典型有效輸入的正常使用(正常路徑)
2. 邊界條件(空輸入、單個項目、最大值、最小值)
3. 應該拋出錯誤或返回錯誤狀態的無效輸入
4. [任何特定領域的案例,例如「資料庫呼叫失敗的情況」]
5. [任何並發或非同步行為,如果適用]
需求:
- 使用真實的測試數據,而不是「test」或「1234」等佔位符
- 命名每個測試以描述場景和預期結果
- 在每個測試群組上方添加簡短的注釋解釋被測試的內容
- 模擬任何外部依賴([列出它們,例如「資料庫呼叫」、「HTTP 請求」])
技巧與最佳實踐
-
每個行為一個測試,而不是每個函數一個測試 — 請 Claude 為每個不同的行為撰寫一個測試,而不是每個函數一個大測試。「每個測試應該只驗證一件事。如果一個測試有多個邏輯斷言群組,拆分它。」 這使測試失敗能精確指出確切的問題。
-
請求正面和負面斷言 — 許多測試套件只驗證事情正確運行。請 Claude 也撰寫無效狀態的測試:「包含驗證函數在給定無效輸入時拋出正確的異常類型(不只是任何異常)的測試。」
-
生成基於屬性的測試描述 — 對於具有數學屬性的函數(交換律、冪等性、單調性),請 Claude 描述不變量:「對於這個函數,不管輸入如何,哪些屬性應該始終成立?描述它們,如果框架支持的話撰寫基於屬性的測試(例如 Python 的 Hypothesis、JavaScript 的 fast-check)。」
-
請求測試數據工廠,而不是硬編碼的固定裝置 — 對於實體密集的測試,請 Claude 生成工廠函數而不是硬編碼對象。「不要硬編碼的測試對象,而是撰寫一個帶有合理預設值和關鍵字覆蓋的
make_order()工廠函數,這樣每個測試只能定制對它相關的欄位。」 -
讓 Claude 在撰寫測試之前撰寫測試計劃 — 對於複雜的程式碼,先請求測試計劃:「在撰寫任何程式碼之前,列出你計劃測試的所有場景以及原因。我會審查計劃,然後你可以撰寫測試。」 這在你承諾特定測試實作之前浮現覆蓋策略決策。
動手試試
從你的程式碼庫中選取一個純函數——一個沒有副作用、沒有外部依賴,只是輸入進輸出出的函數。用這個提示貼入 Claude:
「為這個函數撰寫全面的 pytest 測試。涵蓋:至少 3 個不同有效輸入的正常使用、邊界條件(空、None、單元素清單、非常大的值——任何相關的),以及至少 3 個應該拋出異常的無效輸入案例。使用真實的測試數據,並命名每個測試以描述場景。」
運行生成的測試。看看 Claude 考慮了多少你自己不會撰寫的邊界情況。