Claude Code 寫 test 唔濫:critical path 100% / hot path 80% / cold path 0%
Claude Code 開晒 test 就寫到 100% coverage,但好多 test 對 production 安全完全冇貢獻。教三層 coverage strategy:critical / hot / cold path 分清楚,CLAUDE.md 寫明邊個 module 屬邊層,Claude 自動知幾深寫。
情境
你叫 Claude Code 加 test。15 分鐘後佢出咗 47 個 test file、coverage report 顯示 98.6%。你睇個 dashboard——綠色一片,好滿足。
兩個禮拜後 production 數據錯。睇返 test:
- Payment module:覆蓋率 100%,但全部 test 都係 happy path,冇一個係 currency rounding 嘅邊界情況
- Admin dashboard 嗰個 CSV export script:覆蓋率 100%,3 個 test,每個 test 都喺 mock 一個 mock,零實際保護
- 然後個真正關鍵嘅 RBAC 權限檢查 function——
isAllowed()——只係 1 個 test。「你叫我加 test 我就平均加,呢個 file 細,所以加少啲」
呢個係 Claude Code 嘅慣性失誤:佢冇你個 production 風險嘅心智模型,所以佢平均咁鋪開 test,但風險集中嘅地方反而覆蓋唔夠。
解法唔係寫多啲 test,係將覆蓋策略寫死入 CLAUDE.md,叫 Claude 按你定義嘅三層自動分輕重:
- Critical path:payment、auth、data write、權限檢查 — 100% 覆蓋 + 邊界情況 fuzz
- Hot path:用戶日常 flow(login、search、checkout UI)— 80% smoke + integration
- Cold path:admin 工具、一次性 script、internal dashboard — 0% test,靠手動
呢篇拆呢個策略點落地,等 Claude Code 自動知邊度該深、邊度該淺。
跟住做
1. 識別你個 codebase 嘅三層
開始前,揀 5 分鐘對住 file tree 過一次,每個 module 貼一個 label:
Critical path(每個 codebase 通常得 5-15%):
- Payment / billing / subscription
- Auth / session / token generation
- 權限檢查 / RBAC / row-level security
- 會改動 business state 嘅 data write(order placement、inventory deduction)
- Audit log writer
Hot path(30-50%):
- 用戶常用 UI flow(search、filter、profile edit)
- 畀已登入用戶用嘅 API endpoint
- 計算 derived data(dashboard metric、report aggregation)
- Email / notification 觸發
Cold path(剩低嗰 40-60%):
- Admin 專用工具(user search、退款處理 — 手動用,錯咗你即時知)
- Dev script(DB seed、migration helper、import job)
- 一次性 marketing landing page 嘅邏輯
- Internal dashboard,得 3 個同事用
- Documentation generator
重點:唔好對 cold path 內疚。Cold path 嘅回報喺手動 + 監測,唔喺 test。
2. 寫 coverage policy 入 CLAUDE.md
呢段係唯一準則。Claude Code 每個 session 都讀,自動知幾深寫。
## Test Coverage Policy
呢個 codebase 用三層 coverage strategy。寫 test 之前確認你知個 module 屬邊層:
### Critical path(100% + edge case fuzz)
Module:
- src/payment/**
- src/auth/**
- src/permissions/isAllowed.ts
- src/inventory/deduct.ts
- src/audit/logger.ts
要求:
- 100% line + branch coverage
- 每個 input 邊界 case 都寫 test(null、負數、零、極大、Unicode)
- 每個 business rule edge case 都寫 test(過期 token、race condition、partial failure)
- 改呢層任何 file 之前,問我「需唔需要加 test?」
### Hot path(80% smoke + integration)
Module:
- src/app/**(除咗 admin 同 internal)
- src/api/public/**
- src/components/**(user-facing)
要求:
- Happy path + 2-3 個常見錯誤 case
- Integration test cover 主要 user flow
- 唔需要 100%;80% 已經夠
### Cold path(0% — 唔好寫 test)
Module:
- src/admin/**
- scripts/**
- src/internal/**
- src/app/(marketing)/**
要求:
- **唔好** auto 加 test
- 如果我明確叫你寫 test 先寫
- 改 cold path file 唔需要 propose test
關鍵設計:按 path 分,唔係按 feature 分。Claude 一睇 file path 就分到層,唔需要每次問你。
3. 對應每層嘅 test prompt
每層 test 嘅寫法唔同。critical path 要逼出邊界情況,hot path 要 smoke 鋪得廣,cold path 完全唔好寫。
Critical path 寫 test:
呢個係 critical path module(睇 CLAUDE.md coverage policy)。階段一:唔好寫 test code。先列: Input boundary(null、undefined、empty、negative、極大、Unicode、whitespace) Business rule edge(過期、未生效、partial state、concurrent modification) External failure(DB timeout、API 5xx、network partition) 每個情況 1 句描述 + 1 個 test name。階段二:我揀邊幾個寫,你就按我揀嘅寫出 test code。唔好自己加情況。
Hot path 寫 test:
呢個係 hot path module。寫 smoke + integration test: 1 個 happy path 2-3 個常見 user error(empty input、invalid format、unauthorized) 唔需要覆蓋罕見嘅邊界情況 目標覆蓋率 80%,唔需要 100%。寫完同我講你略過咗邊類情況 + 點解。
Cold path:
呢個係 cold path file(睇 CLAUDE.md)。改完唔好主動提議加 test。如果你覺得呢段邏輯有風險,喺回覆入面講你嘅憂慮,由我決定要唔要升做 hot path。
4. 睇 coverage report 嘅正確角度
跑完 pnpm test --coverage,唔好睇 overall %。整體覆蓋率係虛榮指標——cold path 拉低個數但唔代表風險高。
正確睇法:
# 只睇 critical path 嘅 coverage
pnpm test --coverage --coverageDirectory=coverage \
--collectCoverageFrom='src/{payment,auth,permissions,inventory,audit}/**'
目標:critical path 段嘅 line + branch 覆蓋率 99%+。Hot path 80%+。Cold path 唔睇。
如果 critical path 跌穿 99%,呢個係 P0 警號——比整體由 85% 跌去 80% 嚴重 10 倍。
變化例子
變化 1:B2B SaaS — audit log + RBAC 升做 critical
B2B 客戶嘅合約通常寫死要有 audit log + RBAC 執行。一爆出嚟就係合規問題、唔係 bug。
呢類 codebase 嘅 critical path 要擴:
### Critical path(B2B SaaS 補充)
- src/audit/**(所有 audit log writer + reader)
- src/rbac/**(permission check、role assignment、scope filter)
- src/tenants/isolation.ts(multi-tenant data leak 嘅最後一道防線)
- src/webhook/signature.ts(incoming webhook auth)
邊界情況 fuzz 要特別狠:tenant A 嘅 user 試攞 tenant B 嘅 data、已停用 user 嘅 token 仲有效、role downgrade 之後 in-flight request 點處理。每個都寫明確嘅 test。
變化 2:電商 — payment + inventory 唔可以分享 state assumption
電商最痛係兩個 critical module 互相依賴:payment 成功但 inventory deduct 失敗、或者反過嚟。Test 嘅時候唔可以將對方 mock 做「永遠成功」。
### Critical path(電商補充)
- src/checkout/**(order placement orchestration)
- src/payment/**(charge、refund、partial refund)
- src/inventory/{deduct,restock}.ts
- src/pricing/**(discount、tax、currency conversion)
特別要求:
- Payment + inventory 嘅 integration test 要 cover「一邊成功一邊 fail」
- 唔可以 mock 對方做 happy path 通過;必須 test compensation logic
呢類 codebase 嘅 hot path 反而可以鬆啲——product listing、search filter、wishlist 呢啲,80% smoke 就夠。
變化 3:Content site(似呢個 project 自己)— 大部分都係 cold path
呢個 newsletter project 嘅 coverage policy 真係寫得好短:
### Critical path
(暫時冇 — 無 payment、無 auth、無 user data)
### Hot path
- src/lib/content.ts(MDX query helper — 影響全部 page 嘅 build)
- velite.config.ts(schema 改錯全站爆)
### Cold path
- 所有 component(visual feedback 比 unit test 快)
- 所有 MDX content
- 所有 utility script
Content site 嘅風險狀況同 B2B SaaS 唔同。呢度 build fail 就立即知、deploy preview 一睇就睇到 layout 爛——手動 loop 快過任何 test suite。覆蓋率整體可能得 20%,但 critical path 嘅 0 個 module × 100% = 完美達標。
唔好覺得呢個係偷雞。務實覆蓋嘅核心係:test 嘅回報取決於「冇 test 嘅壞處有幾大」。Content site 冇咩壞處,test 嘅回報就低。
拆解:點解 work,同邊度會仆街
跟到上面就用得。下面呢段係寫畀**想由「一個 sprint 跟到」做到「半年後個 codebase 改晒樣都仲信得過呢套分層」**嘅人——初學者可以跳過,唔影響你跟住做。
呢套分層最唔老實嘅地方係:第一日貼好 label 唔代表三個月後仲啱。codebase 會生,module 會搬,path 會改名。呢套策略實際會喺呢幾個位仆街,你要預咗:
1. Path glob 一改名就靜靜雞失效
你 CLAUDE.md 寫死 src/permissions/isAllowed.ts 係 critical path。有日你 refactor,搬咗去 src/auth/permissions/check.ts。CLAUDE.md 冇人同步改。
- 點解錯:Claude 一睇新 path 對唔上任何 critical glob,就當佢係 cold path——你最關鍵嘅權限檢查靜靜雞跌出咗保護網,冇報錯、冇紅字,你完全唔知。
- 點救:將 coverage policy 嘅 path 同 import 真實結構掛鈎,refactor 嘅 prompt 明寫「如果你搬咗 critical / hot path 入面任何 file,順手更新 CLAUDE.md 嘅 path glob,喺回覆度列出改咗邊行」。定期叫 Claude 對一次「policy 列嘅 path 有冇已經唔存在」。
2. Coverage 數字靚,但 test 喺 mock 一個 mock 情境段講過嗰個 CSV export「3 個 test 全部 mock 一個 mock」。critical path 一樣會中招:你逼到 line + branch 99%,但每個 dependency 都 mock 做「永遠成功」,等於 test 緊個 mock,唔係 test 緊你嘅 logic。
- 點解錯:覆蓋率係「行有冇被執行過」,唔係「行為啱唔啱」。100% 綠燈可以完全冇 assert 過真正嘅 business rule,partial failure 一發生 production 即爆。
- 點救:critical path 嘅 prompt 明寫「唔可以將同層嘅 critical dependency mock 做 happy path」(電商變化嗰段已經點咗呢樣,但要當通則)。Review test 嗰陣睇 assert 喺度 assert 乜,唔好淨係睇個 coverage %。
3. Cold path 偷偷升咗呢,但冇人升 label
你個 admin 退款工具開頭真係手動用、錯咗即刻知。但生意做大咗,呢個工具開始夜晚自動跑 batch refund,冇人睇住。佢仲喺 src/admin/**,仲係 0% test。
- 點解錯:「錯咗即時知」呢個假設係 cold path 0% 嘅唯一理由。一旦冇人睇住自動跑,呢個假設就破咗,但 path 冇變、policy 冇變,風險靜靜雞由 cold 變 critical。
- 點救:定期問返自己「邊啲 cold path 已經由人手變自動、由有人睇變冇人睇」。一升做自動 / 一掂到錢同權限,就即刻搬個 file 入 critical glob。分層係活嘅,唔係貼一次就封存。
4. Claude 對「邊界情況」嘅想像力,受你個 prompt 框死 critical path 階段一叫 Claude 列 input boundary、business rule edge、external failure。佢列得幾好,取決於佢估唔估到你個 domain 嘅暗坑。你冇講「呢個系統有 multi-currency」,佢就唔會諗到 currency rounding——正正就係情境段爆嘅嗰個。
- 點解錯:LLM 唔知你冇講出口嘅 domain 假設。漏咗嘅邊界唔會報錯,佢只會喺 production 用真錢示範畀你睇。
- 點救:階段一收到佢列嘅清單之後,唔好即刻揀,反問「以我哋係 [你個 domain:multi-currency / multi-tenant / 有 webhook retry] 嘅系統,你仲漏咗邊類邊界?」逼多一round。寧願階段一拗耐啲,好過階段二寫到靚但漏咗死穴。
呢幾個位,就係「貼一次 label 個 dashboard 好睇」同「半年後 codebase 改晒樣個分層仲信得過」之間嘅距離。
100% 覆蓋率唔等於 100% 安全。Test 寫喺低風險嘅地方,等如將你嘅注意力分散——關鍵 bug 走出去嘅機會反而高。覆蓋嘅藝術唔係多,係準。
香港 dev 嘅務實底線:critical 100%、hot 80%、cold 0%。寫死入 CLAUDE.md,等 Claude Code 自動分到層,你就唔需要每次同佢拗「呢個 file 要唔要 test」。
文中工具 · 連結
- Claude Code CLI· 付費
開發者用 — terminal 入面同 Claude pair coding
睇完想同 Claude 一齊行一次?
撳一撳,就將成段 tutor 指示(連埋成篇文嘅內容)抄入剪貼簿。 貼入 Claude.ai 或 Claude Desktop,佢會用廣東話帶你一步一步行, 每步問你填關鍵位,最後畀返一個專為你情況寫嘅 prompt 帶走。
- 創作者 · 50 分鐘
Claude Code 行 TDD:你寫 test,Claude 寫 impl — pair-programming 模式真係 work
Claude Code TDD 工作流:你負責 test、Claude 負責 impl 嘅 pair programming 模式。red-green-refactor 具體 prompt + edge case ratchet + 邊類問題啱用 TDD。
- 創作者 · 25 分鐘
Claude Code Hooks:自動排版 / 自動 test / 自動 block 危險指令
成日唔記得跑 prettier,commit 就 lint fail。或者擔心 Claude 突然跑 `rm -rf /`。Hooks 解決:PreToolUse 阻破壞性指令,PostToolUse 自動排版。教你 setup 5 個必備 hook + 邊個事件對邊類任務。
- 創作者 · 60 分鐘
Claude Code 做 safe refactor:先 characterization test、後 mechanical move、再核對等價性
Claude Code 做 safe refactor 嘅三步流程:先 characterization test 釘住現有行為、再 mechanical move 唔改邏輯、最後核對等價性。教你避開 AI 直接重寫撞爛 edge case 嘅死位。