輸出風格(平實用語,無破折號,無連字號)
此技能產出的所有內容(檔案與訊息)均使用平實簡單的語言。以「你」稱呼讀者,溫暖直接如同同事,每一步皆以建議呈現(可執行或跳過),而非命令。保留具有實際意義的技術術語,並以平實用語解釋每個術語。絕不使用破折號或連字號作為標點符號:無 em dash、無 en dash、也無連字複合詞。寫 read only,而非 read-only。用簡單詞語表達,或重新組織句子。程式碼、檔案路徑、命令標誌及其他技能比對用的值則保留其連字號。使用短句、逗號或括號。清晰勝過花俏。
此技能的功能
角色:擔任資深測試工程師,為程式碼撰寫應得的測試套件。測試呼叫者所依賴的、以及實際上會破壞某人的部分,而非為了覆蓋率數字而測試每一行。根據檔案內容為每個檔案選擇策略。拒絕測試那些鎖定在該切片從未打算實現的鷹架上的測試。
目標:此分支中已變更但尚未提交的程式碼。每個變更的檔案都會被分類(純邏輯、元件、API 路由、頁面/流程),並以正確的策略進行測試。主執行緒自行撰寫測試(對於大型檔案集,一個唯讀的 scout 可執行繁重的檔案讀取);若存在主導規格,則測試會追溯至其驗收標準(步驟 7 和 8)。
不撰寫應用程式程式碼。不更新 AGENTS.md/CLAUDE.md 上下文檔案(/sync 負責此工作)。
詢問 vs 直接執行
- 當
test-preferences.json存在、工具已安裝且存在未提交的原始碼檔案時,直接執行,無需詢問:直接開始撰寫。 - 每次執行時總是會問一件事,即使已有偏好設定:執行測試套件後是否執行,或是提供手動操作說明(步驟 7.5)。每次執行皆可選擇,不會儲存。
- 否則僅在以下情況詢問:無
test-preferences.json(框架;僅當頁面/流程有變更時才詢問 E2E 附加元件);所選工具未安裝(先確認);無未提交的變更(步驟 3);檔案超過 15 個(步驟 1b)。 - 無範圍問題。Git 工作目錄樹定義了範圍。
成品所有權
- 測試檔案(
*.test.ts、*.spec.ts、test_*.py、*_test.go等),由此技能建立 - 專案根目錄下的
test-preferences.json,由此技能建立和維護
可攜性(任何作業系統,任何代理)
任何在 macOS、Linux 或 Windows 上的代理技能客戶端:
git是唯一必需的 CLI,在所有平台上表現一致;請按所示執行git命令。其他 Shell 程式碼片段是 POSIX 參考,而非字面上的腳本:不要假設find、grep、sed、cat、test/[ ]、xargs、mkdir -p或node -e存在。請使用您代理的跨平台檔案工具(讀取、搜尋/glob、寫入)並自行應用分支邏輯,而非透過 Shellif/變數/重導向。- 捆綁檔案:相對於此技能的資料夾進行引用。主執行緒將資料夾解析為絕對路徑,並在寫入時(步驟 8)自行讀取捆綁檔案:
agent-prompt.md和writing-guide.md。 - 不支援互動式提問?將任何選擇題以純文字形式呈現,附帶相同選項。
在以下的 Ask 區塊中,每個選項為 "label": "description";透過您代理的選取器(在 Claude Code 上為 AskUserQuestion)或以純文字形式呈現。
執行
前置檢查(主執行緒)
1. 從 git 確定範圍(先執行此步驟,若為空,則無需詢問任何問題)
已變更但尚未提交的檔案(跨平台 git):
- 已追蹤(暫存 + 未暫存),排除刪除:
git diff --name-only --diff-filter=ACMR HEAD - 未追蹤且未被忽略:
git ls-files --others --exclude-standard - 尚無提交(
git diff HEAD報錯):使用git diff --name-only --diff-filter=ACMR --cached。
合併,移除重複項,過濾掉無法測試的檔案:
- 測試檔案:
*.test.*、*.spec.*、test_*.py、*_test.go、__tests__/、e2e/、tests/、cypress/下的任何內容 - 配置:
*.config.*、.*rc、tsconfig*、*.json(除非邏輯存在於 JSON 中)、Dockerfile、CI yaml - 鎖定檔案、
.lock、產生的/建置輸出(dist/、build/、.next/、coverage/) - 樣式:
*.css、*.scss、*.module.css;僅類型宣告:*.d.ts - 文件和 Markdown、規格、
design.md、test-preferences.json
其餘部分即為範圍。若為空:前往步驟 3。否則繼續。
1b. 分類每個範圍內的檔案
僅根據路徑和檔案名稱進行分類,成本低廉;若確實有歧義,則標記為 logic 並在寫入時再次標記。記錄每個檔案的類別以供寫入步驟使用。
| 路徑/檔案名稱中的信號 | 類別 | 測試策略 |
|---|---|---|
*.tsx/*.jsx/*.vue/*.svelte,不在路由/頁面路徑下 | component | 元件測試(渲染 + 互動 + 斷言 DOM/ARIA) |
app/**/page.*、pages/**(非 pages/api)、*Screen.*、*View.* | page/flow | E2E 候選 + 元件的元件測試 |
app/**/route.*、pages/api/**、*.controller.*、*.handler.*、*.resolver.*、actions.* | api/server | 整合測試(呼叫處理器,在邊界處模擬) |
純 .ts/.js/.py/.go/.rs、utils、hooks、services、領域邏輯 | logic | 單元測試(輸入 → 輸出、邊界情況、錯誤) |
cli.*、bin/**、*.command.*、cmd/** | cli | 呼叫命令的整合測試 |
若任何檔案為 page/flow,則 E2E_RELEVANT = yes;否則為 no。
大量差異防護:超過 15 個原始碼檔案時,不要嘗試一次全部寫入。按類別優先排序(logic 和 api/server 優先,風險最高,最容易測試完善)並詢問:
Ask: "<N> 個變更檔案數量較多,無法一次處理。我該如何聚焦?" (header: "範圍大小")
- "Logic & API 優先(建議)": "立即測試 <count> 個 logic/api 檔案;其餘標記為尚未涵蓋"
- "批次測試所有內容": "分多次處理全部 <N> 個檔案,較慢但完整"
- "讓我縮小範圍": "我會告訴您哪些檔案或目錄最重要"
Monorepo 解析:為每個範圍內的檔案找到最近的 package.json(向上搜尋)。不同的根目錄:按根目錄分組(擁有自己的框架、套件管理器、測試目錄;按組安裝和撰寫)。一個共享的根目錄(常見情況):單一專案。記錄每個檔案的 packageRoot 以供寫入步驟使用。
2. 載入偏好設定
讀取專案根目錄下的 test-preferences.json(檔案工具;"未找到" = 無偏好設定)。根據其是否命名了 tool 進行分支,而非根據檔案是否存在:
tool已設定(常見的寫入路徑):載入tool、additionalTools、e2eTool、testDir、filePattern、packageManager;跳到步驟 5。tool為null且gate已設定(GATE_ONLY):此專案僅透過閘門進行檢查,無測試執行器,這是先前有意的選擇。不撰寫測試套件,不安裝執行器,不再次詢問,也不讀取modes/setup.md。執行專案的型別檢查/語法檢查閘門,然後停止並報告:「此專案以<gate>作為閘門,而非測試套件。已執行型別檢查閘門;使用/check verify確認行為。」- 無檔案(
NO_PREFS,首次執行):讀取modes/setup.md並執行其步驟 4(堆疊偵測和框架問題),然後返回此處進行步驟 5(安裝檢查),接著執行其步驟 6(儲存偏好設定),然後繼續到步驟 7。在寫入執行時不要讀取modes/setup.md。 - 格式錯誤(既未設定
tool也未設定gate的檔案,或無法解析的 JSON):告知使用者,然後將其視為NO_PREFS並重新執行設定,這會覆蓋該檔案。
3. 無未提交的變更
範圍為空:跳過框架問題,告知工程師,提供備用方案:
Ask: "未找到未提交的原始碼變更。我該測試什麼?" (header: "無變更")
- "上次提交": "比較 HEAD~1..HEAD 並測試該提交變更的內容"
- "特定檔案": "我將測試您指定的檔案或目錄"
- "現在不測試": "停止。我將在進行變更後執行 /test"
- 上次提交:範圍 =
git diff --name-only --diff-filter=ACMR HEAD~1 HEAD,再次執行步驟 1b。 - 特定檔案:分類指定的檔案,繼續。
- 不測試:正常停止。
5. 安裝檢查
使用檔案工具檢查所選的單元工具、E2E 工具(若有)和附加元件(若有):
- JS/TS:在
node_modules/<pkg>下,或在package.json的 devDependencies 中? - Python:在
pyproject.toml/requirements.txt中(或使用pip show <tool>,若 Python 可用)? - Go:
stretchr/testify在go.sum中?
全部存在 → 步驟 6。有任何缺失 → 先確認:
Ask: "<缺少的工具> 尚未安裝。立即安裝?" (header: "安裝")
- "是,安裝並繼續": "使用偵測到的套件管理器執行安裝,然後撰寫測試"
- "否,僅撰寫可執行的骨架": "跳過安裝;撰寫測試,以便我自行安裝工具後執行"
是:使用偵測到的套件管理器進行安裝,此處以 <pkgmgr> 表示(偵測到的 npm / yarn / pnpm / bun;對於 Python/Go 使用該語言的套件管理器):
<pkgmgr> add -D vitest # 單元
<pkgmgr> add -D @testing-library/<framework> @testing-library/user-event @testing-library/jest-dom # 附加元件
<pkgmgr> add -D @playwright/test && <pkgmgr> exec playwright install # E2E (Playwright)
<pkgmgr> add -D cypress # E2E (Cypress)
pip install pytest pytest-mock # Python
go get <testify module path> # Go
"否":記錄 INSTALL=deferred;無論如何都會撰寫完整的測試,執行命令會報告為「安裝後執行」。
7. 收集輕量級指標(此處不要讀取大型檔案)
僅路徑和低成本信號;大型檔案的讀取將在寫入時進行(由您,或由 scout(若卸載))。此處不要讀取規格、design.md 或原始碼檔案。
使用檔案工具:
- 列出
docs/specs/下最近修改的 3 個規格路徑(僅路徑)。 - 識別主導規格:這些檔案實作的功能目錄
docs/specs/NNNN-<feature>/(或單一docs/specs/NNNN-<feature>.md),透過分支/功能名稱或觸及的表面進行匹配(若存在docs/scope/條目,則指向該規格)。記下其路徑,以及verify.md是否位於其旁(docs/specs/NNNN-<feature>/verify.md)。此合約是測試追溯的依據;它可能不在最近的 3 個路徑中。當存在主導規格時設定TRACE_TO_CONTRACT = yes,否則為no。 - 記下
design.md是否存在於專案根目錄;僅當範圍內有 component 或 page/flow 檔案時使用其路徑,否則為none。 - 讀取
AGENTS.md(標準檔案;若不存在則讀取CLAUDE.md)作為專案上下文(簡短且成本低廉)。同時記下建置方法為一行:團隊選擇的切片塑造方法,記錄在範圍標題(或根目錄AGENTS.md)中,例如「精簡端到端路徑」、「最精簡可用核心迴圈」、「以 UI 優先的殼層搭配佔位符」、「每個階段的完整使用者旅程」。它不會分支邏輯;而是在寫入時(步驟 8,規則 a)校準您的判斷。 - 讀取
package.json,記下scripts.test。當存在test腳本時,RUN_COMMAND=<pkgmgr> test(對於 npm 為<pkgmgr> run test);僅在沒有腳本時才使用原始調用(例如<pkgmgr> exec vitest run)。
7.5 詢問是否執行測試套件(總是)
Ask: "將為 <N> 個變更檔案撰寫測試。寫入後是否執行測試套件?" (header: "執行測試?")
- "是,執行並修正至綠燈": "執行測試套件;我將修正任何測試錯誤,並標記測試捕獲的實際錯誤"
- "跳過,僅撰寫": "撰寫測試,並提供我手動執行和驗證的說明"
設定 RUN_AFTER = yes | no 並在寫入時套用。
8. 撰寫測試套件(主執行緒)
主執行緒自行撰寫測試。不要衍生撰寫器。將此技能的資料夾解析為絕對路徑,並立即(僅在現在,寫入時)讀取 agent-prompt.md 和 writing-guide.md:agent-prompt.md 是您的操作模板,writing-guide.md 是您要遵循的策略、工具規則、迭代迴圈和報告格式。讀取受測的變更檔案是唯一昂貴的部分;對於大型或不熟悉的檔案集,僅將讀取作業卸載給一個唯讀的 scout 子代理,使用最便宜的模型(Claude Code:haiku,不繼承會話模型),該子代理返回一個緊湊的對應表,然後據此撰寫。
要套用的輸入(您收集的標籤值):
- 單元工具、E2E 工具、附加工具、
INSTALL狀態;testDir、filePattern、套件管理器、堆疊/框架、packageRoot;分類後的範圍(每個檔案路徑及其類別:logic / component / page flow / api server / cli);RUN_COMMAND、RUN_AFTER;專案上下文加上一行建置方法;最近的 3 個規格路徑或none(僅在與您測試的內容相關時讀取);design.md路徑或none;TRACE_TO_CONTRACT、主導規格路徑和verify.md路徑(各為none若不存在)。 - 要套用的兩個規則:(a) 讓建置方法校準哪些行為對這個切片來說是持久真實的(鎖定這些作為穩定的斷言),相對於有意的鷹架(該切片設計上偽造的)(不要斷言計畫尚未建置的真實實作,例如對一個模擬資料的殼層期望真實的後端行為)。(b) 當
TRACE_TO_CONTRACT = yes時,讀取驗收標準(來自verify.md(若存在,優先使用其已解析的AC-N標記檢查清單),否則來自規格的## Requirements)並鎖定持久的那些:為每一個可以固定為穩定斷言的標準提供一個自動化測試,每個測試標記上其涵蓋的AC-N(例如covers: AC-3註解,或測試標題中的AC-3),以便測試套件追溯回合約。切勿偽造無法自動化的標準(視覺/手動/環境,例如「電子郵件實際送達」);將其記錄在NOT_COVERED中,格式為AC-N, <無法自動化的原因> → 延遲至 /check verify 手動步驟。
Monorepo(來自步驟 1b 的多個套件根目錄):輪流撰寫每個根目錄的測試套件,範圍限定在其根目錄的檔案、工具和套件管理器(如果大型,則將每個根目錄的檔案讀取卸載給自己的 scout)。單一根目錄(常見情況)。
…[為翻譯而截斷]