結論先講
AI 是優秀的測試起草者,但糟糕的測試決策者。 讓 AI 產生 boilerplate 測試、發現邊界案例、寫 snapshot 測試——這些它很擅長。但「這個功能該測什麼」、「這個 mock 的行為對不對」、「測試覆蓋的業務場景夠不夠」——這些判斷還是需要人。
2026 年的現狀:AI 可以把你寫測試的時間縮短 40-60%,但如果完全不看 AI 產生的測試就直接 commit,你最後會得到一堆 coverage 數字很漂亮但實際上什麼都沒驗證的測試。
AI 測試工具現況(2026)
Claude Code
Claude Code 的 /test 指令可以直接為指定的檔案或函式產生測試:
# 基本用法
claude /test src/services/order.ts
# 指定測試框架
claude /test src/services/order.ts --framework vitest
# 針對特定函式
claude /test src/utils/price.ts --function calculateDiscount它也能從 PR diff 推斷該寫什麼測試:
# 根據你的改動建議測試
claude "幫我寫這次改動相關的測試" --diffGitHub Copilot
Copilot 在 IDE 裡的 inline 測試建議已經相當成熟:
// 你寫了這個函式
function calculateShippingFee(weight: number, distance: number): number {
if (weight <= 0) throw new Error('Weight must be positive');
if (distance <= 0) throw new Error('Distance must be positive');
const baseFee = 60;
const weightFee = Math.ceil(weight / 5) * 10;
const distanceFee = distance > 100 ? 50 : 0;
return baseFee + weightFee + distanceFee;
}
// Copilot 會建議的測試(在測試檔案裡打 describe 就會觸發)
describe('calculateShippingFee', () => {
it('should calculate base fee correctly', () => {
expect(calculateShippingFee(1, 50)).toBe(70); // 60 + 10
});
it('should round up weight to nearest 5kg', () => {
expect(calculateShippingFee(6, 50)).toBe(80); // 60 + 20
});
it('should add distance surcharge for >100km', () => {
expect(calculateShippingFee(1, 150)).toBe(120); // 60 + 10 + 50
});
it('should throw on negative weight', () => {
expect(() => calculateShippingFee(-1, 50)).toThrow('Weight must be positive');
});
});這種純計算邏輯的測試,AI 生成的品質通常不錯。
AI 測試生成的優缺點
AI 擅長的
| 場景 | AI 的表現 | 為什麼 |
|---|---|---|
| 純函式測試 | 優秀 | 輸入輸出明確,容易推斷 |
| 邊界案例發現 | 很好 | AI 會嘗試 null、0、負數、超大值 |
| Boilerplate 測試 | 優秀 | describe/it 結構、setup/teardown |
| Snapshot 測試 | 很好 | 只要呼叫函式然後 toMatchSnapshot |
| Error handling 測試 | 不錯 | AI 會測所有 throw 路徑 |
| API endpoint 測試 | 不錯 | 標準的 HTTP method + status code |
AI 不擅長的
| 場景 | AI 的表現 | 為什麼 |
|---|---|---|
| 業務邏輯驗證 | 差 | AI 不知道「VIP 打 8 折」的業務規則 |
| Integration 情境 | 差 | 不了解服務之間的互動 |
| Mock 行為正確性 | 差 | AI 會 mock 到你想測的東西 |
| 測試策略決定 | 差 | 不知道哪些場景重要 |
| 非功能需求 | 差 | 效能、安全、併發場景 |
AI 生成測試的常見問題
問題 1:測試 implementation 而不是 behavior
// AI 常常生成這種測試
it('should call repository.save', async () => {
const repo = { save: jest.fn() };
const service = new OrderService(repo);
await service.createOrder({ productId: 1, qty: 2 });
expect(repo.save).toHaveBeenCalledWith(
expect.objectContaining({ productId: 1, quantity: 2 })
);
});這個測試只驗證了「有沒有呼叫 save」,完全沒驗證「訂單建立的業務邏輯對不對」。如果你重構了 createOrder 的內部實作(例如改用 event-driven),測試就壞了,但功能其實沒壞。
該測的是行為:
it('should create order with correct total', async () => {
const product = await ProductFactory.create({ price: 500 });
const order = await orderService.createOrder({
productId: product.id,
qty: 2,
});
expect(order.total).toBe(1000);
expect(order.status).toBe('pending');
});問題 2:Over-mocking
AI 很喜歡 mock 東西,因為 mock 可以讓測試不依賴外部。但 mock 過度會讓你測的是「你的 mock」而不是「你的 code」:
// AI 生成的——mock 了所有東西
it('should process payment', async () => {
const gateway = { charge: jest.fn().mockResolvedValue({ id: 'pay_123' }) };
const notifier = { send: jest.fn() };
const repo = { save: jest.fn() };
const service = new PaymentService(gateway, notifier, repo);
await service.processPayment(100);
expect(gateway.charge).toHaveBeenCalledWith(100);
expect(notifier.send).toHaveBeenCalled();
expect(repo.save).toHaveBeenCalled();
});
// 這測了什麼?測了你 mock 的行為而已。問題 3:測試描述跟實際測試不符
// AI 生成的
it('should handle concurrent orders correctly', async () => {
const order = await createOrder({ productId: 1, qty: 1 });
expect(order).toBeDefined();
});
// 名字寫「concurrent」,但根本沒有併發測試實務工作流程:AI + 人類協作
推薦流程
Step 1: AI 生成初版測試
└── 用 Claude Code /test 或 Copilot
Step 2: 人類審查
├── 刪掉測試 implementation 的測試
├── 修正 mock 策略(減少不必要的 mock)
├── 確認業務邏輯覆蓋率
└── 補上 AI 想不到的場景
Step 3: 人類補寫關鍵測試
├── 核心業務邏輯
├── 跨服務互動
└── Edge case(基於 domain knowledge)
Step 4: AI 輔助 refactor
└── 「幫我把這 5 個測試的重複 setup 抽出來」
實際操作範例
# Step 1: 讓 Claude Code 生成初版
claude "幫 src/services/discount.ts 寫測試,用 vitest"
# Claude 會生成大約 10-15 個測試案例
# 大部分是計算邏輯和 error handling
# Step 2: 人類審查後,發現缺少
# - VIP 會員折扣疊加規則
# - 折扣碼過期處理
# - 同一訂單不能用兩張折扣碼
# Step 3: 人類補上業務邏輯測試
# Step 4: 讓 AI 幫忙重構測試結構
claude "把 discount.test.ts 的重複 setup 用 beforeEach 整理一下"AI 作為測試 Reviewer
比起生成測試,AI 在 review 測試方面其實更有用:
# 讓 AI review 你的測試
claude "review 這個測試檔案,告訴我:
1. 有沒有漏掉的邊界案例
2. 有沒有測 implementation 而不是 behavior 的測試
3. mock 策略對不對
4. 測試命名清不清楚"AI 在這方面的表現比生成測試好,因為它可以看到你的 implementation code 和 test code,推斷你可能漏了什麼。
不同測試類型的 AI 適用程度
| 測試類型 | AI 生成品質 | 人類審查量 | 建議 |
|---|---|---|---|
| 純函式 Unit Test | 高 | 低 | 大量使用 AI |
| API Endpoint Test | 中高 | 中 | AI 起草,人類補業務邏輯 |
| Integration Test | 低 | 高 | 人類主寫,AI 輔助結構 |
| E2E Test | 低 | 高 | AI 只適合寫 boilerplate |
| Snapshot Test | 高 | 低 | AI 很適合 |
| 效能測試 | 低 | 高 | 人類主導 |
| 安全測試 | 中 | 中 | AI 能產 OWASP checklist 測試 |
未來展望
短期(2026-2027)
- AI 生成的測試品質會持續提升,特別是有 codebase context 的情況
- 更好的 mock 策略推斷(基於依賴注入分析)
- IDE 內即時的測試覆蓋率建議
中期(2027-2028)
- AI 作為 test reviewer 成為標準流程
- 基於 production error log 自動產生回歸測試
- AI 分析 test suite 品質(不只是 coverage 數字)
長期
- AI 理解業務邏輯後,可能產生有意義的 integration test
- 但「該測什麼」的決策權,短期內不會離開人類
常見問題
AI 生成的測試算「有寫測試」嗎?
看品質。如果 AI 生成了 100 個測試但都是測 implementation 的,那 coverage 100% 也沒用。重要的是有沒有真正驗證到業務邏輯。AI 生成 + 人類審查 = 有效的測試。AI 生成 + 直接 commit = 自我欺騙。
要怎麼評估 AI 生成的測試品質?
三個指標:1)Mutation Testing 分數(用 Stryker)——AI 生成的測試能不能抓到刻意植入的 bug;2)刪掉某個測試後 coverage 有沒有掉——如果沒掉,這個測試就是廢的;3)改了 implementation 後測試有沒有壞——如果壞了但功能沒變,代表測的是 implementation。
Claude Code 和 Copilot 哪個生成測試比較好?
取決於 context。Claude Code 可以讀整個 codebase 的 context,生成的測試對跨檔案的依賴處理得比較好。Copilot 在 inline 建議方面更流暢,適合邊寫 code 邊補測試。兩個可以互補。
全部用 AI 寫測試,人力可以省多少?
寫測試的時間大約省 40-60%,但 review 測試的時間會增加。整體來說,資深工程師用 AI 輔助可以提升 30-40% 的測試產出效率。但初級工程師如果不審查就直接用,反而會創造更多技術債。