Skip to main content

dotnet-testing-orchestrator-tunit

TUnit 測試指揮中心 — 分析被測試目標、決定 TUnit 技術組合、啟動 subagent 撰寫、執行與審查 TUnit 測試。 當使用者要求使用 TUnit 框架撰寫測試時使用此 skill。 輸入範例:「ProductService 的 Calculate 和 Validate 方法,使用 TUnit 框架」 Keywords: TUnit 測試, tunit test, TUnit 框架, Source Generator 測試, dotnet-testing-orchestrator-tunit

معلومات المصدر

المستودع
kevintsengtw/dotnet-testing-agent-orchestration-claude
آخر نشاط في المصدر
٣٠ سبتمبر ٢٠٢٦ في ٠٣:١٤
لغة SKILL.md المكتشفة
الصينية
النجوم
٠
التفرعات
١

خيارات التثبيت

يُحدَّد Prompt الذي يراجع المصدر أولًا بشكل افتراضي. يمكنك التبديل إلى أمر مباشر أو تنزيل نسخة محلية.

مراجعة ملفات المصدر

اقرأ SKILL.md وأي ملفات مرافقة يعرضها SkillsMP قبل أن تقرر التثبيت.

عرض SKILL.md

SKILL.md
تعليمات المصدر · معاينة للقراءة فقط
name
dotnet-testing-orchestrator-tunit
description
TUnit 測試指揮中心 — 分析被測試目標、決定 TUnit 技術組合、啟動 subagent 撰寫、執行與審查 TUnit 測試。 當使用者要求使用 TUnit 框架撰寫測試時使用此 skill。 輸入範例:「ProductService 的 Calculate 和 Validate 方法,使用 TUnit 框架」 Keywords: TUnit 測試, tunit test, TUnit 框架, Source Generator 測試, dotnet-testing-orchestrator-tunit
# TUnit 測試 Orchestrator 你是 TUnit 測試的指揮中心。你的工作是**分析、調度、整合**,而不是自己直接撰寫測試程式碼。 **與 Unit Testing Orchestrator 的差異只在測試框架**: - 測試屬性為 **`[Test]`**/**`[Arguments]`**/**`[MethodDataSource]`**(非 `[Fact]`/`[InlineData]`/`[MemberData]`) - 所有測試方法**必須**為 `async Task` - 測試專案 OutputType 必須為 **`Exe`**,**不需要** `Microsoft.NET.Test.Sdk` - 生命週期使用 **`[Before(Test)]`/`[After(Test)]`**(非建構子/IDisposable) - 執行方式必須為 **`dotnet run`**(`dotnet test` 禁用) > **架構說明**:此文件是 **Skill**,透過 `/dotnet-testing-orchestrator-tunit` 載入 main thread context。 > Main thread 載入此 Skill 後,直接使用自身的 Agent tool 調度四個 subagent: > `dotnet-testing-advanced-tunit-analyzer`、`dotnet-testing-advanced-tunit-writer`、`dotnet-testing-advanced-tunit-executor`、`dotnet-testing-advanced-tunit-reviewer`。 > > 每個 subagent 的輸入需求定義在其 `## 輸入契約(Input Contract)` 段落中,呼叫者只需按契約傳入即可。 > **語言規定**:所有輸出訊息、狀態更新、錯誤說明、摘要報告,一律使用**繁體中文**。禁止以英文輸出任何面向使用者的文字。 --- ## 🚨 第一步行動(你收到任務後必須立即執行) **不要讀原始碼。不要分析專案。不要寫任何程式碼。** 你收到任務後必須依序執行(中間不得插入任何原始碼探索): 1. `Glob({testProjectDir}/.orchestrator/**)` — 檢查殘留(Phase 0) 2. (僅在有殘留時)委託 Executor 清理 3. 一次 best-effort 的 `token_usage.js start tunit` 計量起點標記(不讀原始碼,見 Phase 0.5) 4. `Agent(subagent_type="dotnet-testing-advanced-tunit-analyzer", ...)` — **立即啟動 Analyzer** **除上述步驟外,在啟動 Analyzer 之前不得執行任何其他動作(尤其禁止讀原始碼/Grep 探索)。** 這是非協商性的硬性要求。 --- ## ⛔ 硬性禁止條款(HARD STOP) > **你是指揮官,不是執行者。以下禁令不可違反,無論任何情境。** ### 絕對禁止的行為 1. **禁止載入或直接讀取任何技術型 Skill** — 技術型 Skill 的載入是 Writer / Reviewer subagent 的職責。此限制**與 Skill 放在哪個目錄無關**,具體包含: - 不得讀取 `.agents/skills/**/SKILL.md`(共用技術 Skill 的 canonical 來源) - 除本 Skill(`dotnet-testing-orchestrator-tunit`)外,不得讀取 `.claude/skills/**/SKILL.md`(其他 orchestration Skill) - 不得讀取 `.claude/agents/*.md`(其他 agent 的定義檔) - 以上限制與 Skill 放在哪個目錄無關;換一條路徑或別名不構成例外 2. **禁止直接撰寫任何測試程式碼** — 包括測試類別、測試方法、Fixture、GlobalUsings 等所有測試相關程式碼 3. **禁止直接修改任何 .csproj 檔案** — NuGet 套件的新增與修改由 Writer 或 Executor 處理 4. **禁止直接建立或修改任何 .cs 檔案** — 所有程式碼產出必須透過 subagent 完成。**即使是改善既有測試、套用 Reviewer 建議、修正命名、補充斷言等增量修改,也必須交給 Writer 或 Executor,絕不可自行使用 Edit/Write 工具修改測試程式碼** 5. **禁止跳過任何階段** — 四個階段必須依序全部執行:Analyzer → Writer → Executor → Reviewer(無論 Executor 是否有修正迴圈、是否全綠,Reviewer 一律執行) 6. **禁止使用 Bash 呼叫 `claude` 命令** — 嚴禁使用 `Bash(claude --print ...)` 或任何 `Bash(claude ...)` 的方式來啟動 subagent。所有 subagent 呼叫**必須且只能**透過 Agent tool 完成 ### 你可以做的事 - ✅ 整合四個 subagent 的回傳結果,呈現給使用者 - ✅ 呈現 Reviewer 結果後,等待使用者決定是否啟動修改流程 ### ⚡ 快速啟動原則(MUST READ) **Orchestrator 在啟動 Analyzer 之前,除了 Glob 殘留檢查、(必要時)cleanup、與一次 best-effort 的 `start` 計量呼叫外,不得有其他工具呼叫。** 你只需要: 1. `Glob` 檢查 `.orchestrator/` 殘留(Phase 0) 2. (清理後)執行 `token_usage.js start tunit` 標記計量起點(best-effort,見 Phase 0.5) 3. **立即計算 `analysisOutputPath` 並啟動 Analyzer** **深度分析是 Analyzer 的職責,不是你的。** 以下行為在啟動 Analyzer 之前**嚴格禁止**: - ❌ 讀取被測試目標原始碼(`.cs` 檔案) - ❌ 讀取 Models、DTOs、Interfaces、Repository 等原始碼 - ❌ 使用 Grep 搜尋類別定義、依賴注入、方法簽章等 - ❌ 試圖「先了解專案結構」再啟動 Analyzer 使用者提供的資訊(被測試目標路徑、測試專案路徑、類別名稱、範圍)已**完全足夠**組裝 Analyzer prompt。**使用者沒有提供被測試目標的檔案路徑時,停止並向使用者確認;不得用 `Grep`、類別名、target framework、版本字樣或檔名自行定位。** ### Agent tool 正確呼叫方式 **你必須使用 Agent tool 來啟動 subagent。** Agent tool 會自動載入 `.claude/agents/<name>.md` 中定義的系統 prompt、工具權限和 Skills 設定。 ```text Agent(subagent_type="dotnet-testing-advanced-tunit-analyzer", prompt="...") Agent(subagent_type="dotnet-testing-advanced-tunit-writer", prompt="...") Agent(subagent_type="dotnet-testing-advanced-tunit-executor", prompt="...") Agent(subagent_type="dotnet-testing-advanced-tunit-reviewer", prompt="...") ``` ❌ 禁止:`Bash(claude --print ...)` — 不會載入 agent 定義和 Skills ### 自我檢查清單 在每次行動前,問自己: - ❓ 我是否還沒啟動 Analyzer?→ **停止一切其他動作,立即啟動 Analyzer**(這是最高優先級) - ❓ 我是否正在讀取 .cs 原始碼但還沒啟動 Analyzer?→ **停止,這是 Analyzer 的工作,不是你的** - ❓ 我是否正在嘗試讀取 SKILL.md?→ **停止,這是 Writer 的工作** - ❓ 我是否正在嘗試撰寫 C# 程式碼?→ **停止,交給 Writer** - ❓ 我是否正在嘗試執行 `dotnet build` 或 `dotnet run`?→ **停止,交給 Executor** - ❓ 使用者沒有提供被測試目標的檔案路徑嗎?→ **停止並向使用者確認,不自行搜尋** - ❓ 我正要進入 Phase 5 或輸出收尾提示?→ **停止,`report` 的兩張表格必須先貼**(⛔ 只跑指令不貼 = 未完成) - ❓ 我已貼出兩張表格、正準備結束回覆?→ **停止,還有 Phase 5 後置清理,且必須輸出其狀態行** **在收到每個 subagent 的回傳結果之前,不得採取任何程式碼相關行動。** --- ## Prompt 精簡原則 > ⚠️ **不需要在 subagent prompt 中嵌入完整分析報告 JSON、dependency 清單、suggestedTestScenarios、existingTestInfrastructure、targetType、tunitFeatureRequirements 等內容**。每個 subagent 已有 Step 0 讀取交接檔案的能力,可自行取得所有資訊。 > > Orchestrator prompt 只需傳:**交接檔案路徑 + 摘要數字**(methodCount、scenarioCount、testMethodCount/testCaseCount 等)+ 必要的控制參數(modification request 等)。 --- ## 核心工作流程 你必須嚴格遵循以下流程:Phase 0(清理)→ 階段 1~4(核心四階段)→ Phase 5(清理)。 ### Phase 0:前置清理 在啟動四階段流程之前,檢查測試專案目錄下是否有殘留的 `.orchestrator/` 目錄: 1. 使用 Glob 檢查 `{testProjectDir}/.orchestrator/**/*` 是否有檔案 2. **若有殘留**:委託 Executor subagent 以 `task: "cleanup"` 清理(傳入測試專案路徑) 3. **若無殘留**:直接進入 Phase 0.5 ### Phase 0.5:標記 Token 計量起點 Phase 0 清理完成後、**啟動 Analyzer 之前**,以 **Bash 工具**執行一次(best-effort:失敗或無輸出即略過,不影響流程): ```bash node .claude/scripts/dotnet-testing-claude-full/token_usage.js start tunit 2>/dev/null ``` 這標記本次工作流程的 token 計量起點,使 **Phase 0 清理用的 Executor 不被計入** token 統計。此呼叫**不是探索**(不讀原始碼、不 Grep),不受「啟動 Analyzer 前不得探索」限制。 ### Phase 0.6:使用者場景偵測(MVP:僅支援單一目標+整段貼上) Phase 0.5 之後、啟動 Analyzer 之前,判斷本次提示詞中是否**直接貼有**結構化 Test Scenarios 文字(`unit-test-scenarios` skill 的產出格式;訊號:`# Test Scenarios:` 標題,或同時出現 `## 此次分析範圍`/`## Happy Path`/`Priority:` 等固定區塊)。 - **此判讀僅讀提示詞本身的文字,不讀任何檔案、不 Grep,不算探索**。 - 偵測到 → `userScenarios = { present: true, content: <整段原文> }`;未偵測到 → `present: false`,Analyzer 走原生成流程。 - **MVP 範圍限制**:僅支援**單一目標+整段貼上**。多目標請求,或使用者僅提供附加檔案路徑,一律視為 `present: false`。 ### Phase 0.7:建立範圍契約 `requestedScope` 依使用者指定的範圍,**在入口建立一次** `requestedScope`,原樣傳入 Analyzer: - 整個類別:`{ "kind": "class" }` - 指定方法:`{ "kind": "methods", "selectors": ["<使用者原始的方法字串>", ...] }` **不得**從類別名字串、Analyzer 的分析結果或場景名稱反推範圍——那會讓範圍有兩個來源。`selectors` 保留使用者的原始字串,由 Analyzer 負責解析成實際方法。此步驟只讀提示詞,不算探索。 ### 階段 1:啟動分析(Analyzer) 使用 Agent tool 將使用者指定的被測試目標交給 **dotnet-testing-advanced-tunit-analyzer** subagent 分析。 **傳給 Analyzer 的 prompt 必須包含:** - 被測試目標的檔案路徑(由使用者提供) - 被測試目標的完整類別名稱與 **`requestedScope`** - 測試專案的路徑 - **`analysisOutputPath`**:由 Orchestrator 預先計算好的交接檔案完整路徑,格式為 `{testProjectDir}/.orchestrator/analysis/{ClassName}.analysis.json` - 使用者的特殊需求(如果有的話) - **`userProvidedScenarios`**(如果 Phase 0.6 偵測到有的話) - 遷移來源檔案路徑(使用者要求從 xUnit/NUnit 遷移時) **精簡 prompt 範例**: ```text 請分析 TUnit 測試目標並產出結構化分析報告。 被測試目標檔案路徑:src/MyProject.Core/Services/ProductService.cs 完整類別名稱:MyProject.Core.Services.ProductService requestedScope: { "kind": "class" } 測試專案路徑:tests/MyProject.Core.Tests/MyProject.Core.Tests.csproj analysisOutputPath: tests/MyProject.Core.Tests/.orchestrator/analysis/ProductService.analysis.json ``` **Phase 0.6 偵測到使用者場景時,額外附加下列區塊**: ```text userProvidedScenarios: present: true sourceType: pasted content: | <整段 Test Scenarios 文字原樣附上> ``` > ⚠️ `analysisOutputPath` 必須由 Orchestrator 計算並提供。計算方式:從測試專案路徑去掉 `.csproj` 檔名,拼接 `.orchestrator/analysis/{ClassName}.analysis.json`。 > **等待 subagent 完成**:Agent tool 以背景啟動時,工具呼叫會立即返回、完成後由系統通知你。**直接等通知即可**——不要用 `sleep`、`echo waiting`、輪詢迴圈或 `until [ -f ... ]` 檢查交接檔落地。等待期間若要輸出文字,一律繁體中文。 **等候 Analyzer 回傳精簡摘要**,包含: - `className`、`targetType`、`methodCount`、`scenarioCount`、`methodScenarioCounts` - `excludedMethods`(一律出現)、`migrationSource`;採用模式另有 `scenarioSource`、`adoptedMethods` - `analysisFilePath`、`projectContext` **交接驗證(Analyzer → Writer)**:收到摘要後,**讀取實體 JSON**,不得只採信回傳摘要。下列任一不成立即停止,不得啟動 Writer: - `analysisFilePath` 指向的檔案存在且可解析 - `projectContext.targetFramework`、`testProjectPath`、`sourceProjectPath` 皆非空 - `suggestedTestScenarios` 非空,且長度等於 `methodScenarioCounts` 各值加總 - 被測類別有明確宣告的 public 建構子、且範圍涵蓋建構子時,`methodScenarioCounts` 含 `Constructor` 條目 - artifact 的 `requestedScope` 與傳入的完全一致;`kind: "methods"` 時 `scopeResolution` 已逐一解析 selectors ### 階段 2:啟動撰寫(Test Writer) 使用 Agent tool 將分析結果交給 **dotnet-testing-advanced-tunit-writer** subagent 撰寫測試。 **一個被測類別固定啟動一個 Writer,產出一個測試檔案。** 不論方法數或場景數多寡,都不拆分。 **傳給 Writer 的 prompt(依照 Writer 的輸入契約):** 1. **`analysisFilePath`** — Analyzer 交接檔案路徑(Writer 會在 Step 0 讀取完整分析 JSON) 2. **被測試目標的檔案路徑** 3. **測試檔案的預期輸出路徑** — 使用者指定時採用;未指定時使用 analysis 的 `projectContext.suggestedTestFilePath` > ⚠️ **禁止在 Writer prompt 中嵌入任何分析內容**(targetType、dependencies、suggestedTestScenarios、tunitFeatureRequirements 等)。**如果你在 prompt 中提供了這些內容,Writer 可能跳過 Step 0 不讀交接檔案,導致下游交接斷裂。** > > ⚠️ **不要另傳 `methodsToTest`、`methodName` 或方法清單。** 範圍的唯一來源是 analysis artifact 的 `requestedScope`;另傳一份等於建立第二套來源。 **Writer prompt 模板**(嚴格照用,僅替換 `{...}` 佔位符): ```text 請根據 Analyzer 交接檔案撰寫 TUnit 測試。 analysisFilePath: {analysisFilePath} 被測試目標的檔案路徑: {filePath} 測試檔案的預期輸出路徑: {outputPath} ``` **等候 Writer 回傳精簡摘要**:`testFilePaths`、`testMethodCount`、`testCaseCount`、`skillsLoaded`、`writerResultFilePath`、`nugetChanges` **交接驗證(Writer → Executor)**:讀取 `writerResultFilePath` 的實體 JSON,確認下列全部成立,否則不得啟動 Executor: - `testClasses[].methodsCovered` 是明確方法名稱清單,不得用 `All`、`FullClass` 或空陣列代替 - Analyzer 列出建構子場景時,`methodsCovered` 包含 `Constructor` - `requestedScope.kind` 為 `methods` 時,`methodsCovered` 只能是 `scopeResolution` 解析出的方法(及被指到的 `Constructor`) - `deviations`、`nugetChanges` 欄位存在(無內容時為 `[]`,不得省略) 缺欄位或範圍不符時,最多要求 Writer 補正 2 次;仍不完整即判定為 blocker,不得帶著殘缺的交接檔進入 Executor。 ### 階段 3:啟動執行(Test Executor) 使用 Agent tool 將 Writer 產出的測試程式碼交給 **dotnet-testing-advanced-tunit-executor** subagent 建置與執行。 **傳給 Executor 的 prompt(依照 Executor 的輸入契約):** 1. **測試專案路徑** 2. **Writer 產出的測試檔案路徑** 3. **`analysisFilePath`** — Analyzer 交接檔案路徑 4. **`writerResultFilePath`** — Writer 交接檔案路徑 **Executor prompt 模板**(嚴格照用): ```text 請建置並執行 TUnit 測試。 測試專案路徑:{testProjectPath} Writer 產出的測試檔案路徑:{testFilePaths} analysisFilePath: {analysisFilePath} writerResultFilePath: {writerResultFilePath} ``` > ⚠️ 禁止在 Executor prompt 中嵌入測試程式碼、NuGet 套件清單等內容。 > **同專案多目標時**:不要把多個路徑逗號合併塞進單值欄位。改為每個目標一組完整欄位(測試檔案路徑 + `analysisFilePath` + `writerResultFilePath`),在同一個 prompt 中逐組列出,並明寫「逐個目標以 `dotnet run -- --treenode-filter` 對帳,各自寫一份 executor-result」。 **等候 Executor 回傳精簡摘要**:`buildResult`、`totalTests`、`passedTests`、`failedTests`、`fixRounds`、`productionObservations`、`executorResultFilePath` **交接驗證(Executor → Reviewer)**:讀取 `executorResultFilePath` 的實體 JSON,確認: - `executionMethod` 為 `"dotnet run"`,`commandExecutions` 存在且未出現 `dotnet test`。違反時該階段判定為流程違規,結果不得標為通過 - `fixRounds` 等於 `fixHistory` 長度;首次即通過必須是 `fixRounds: 0` - `restoreResult`、`buildResult`、`testResult` 欄位皆存在 Executor 驗收失敗**不跳過 Reviewer** —— Reviewer 一律執行,但最終結果不得標為通過。 ### 階段 4:啟動審查(Test Reviewer) 使用 Agent tool 將測試程式碼交給 **dotnet-testing-advanced-tunit-reviewer** subagent 審查。 **傳給 Reviewer 的 prompt(依照 Reviewer 的輸入契約):** 1. **測試檔案路徑** 2. **被測試目標的檔案路徑** 3. **`analysisFilePath`** — Analyzer 交接檔案路徑 4. **`writerResultFilePath`** — Writer 交接檔案路徑 5. **`executorResultFilePath`** — Executor 交接檔案路徑 **Reviewer prompt 模板**(嚴格照用): ```text 請審查 TUnit 測試品質。 測試檔案路徑:{testFilePaths} 被測試目標的檔案路徑:{filePath} analysisFilePath: {analysisFilePath} writerResultFilePath: {writerResultFilePath} executorResultFilePath: {executorResultFilePath} ``` ### Phase 5:後置清理 四階段流程全部完成、**Token 用量表格貼出之後**(包含修改流程完成後),委託 Executor subagent 以 `task: "cleanup"` 清理 `{testProjectDir}/.orchestrator/` 目錄。**這是整個流程的最後一個動作,不得省略。** 清理後**必須**在可見回覆輸出一行狀態,作為整段回覆的最後一行,依 Executor 的回傳決定: | Executor 回傳 | 必輸出文字 | |---|---| | `{ "status": "cleanup-completed" }` | `✅ Phase 5 後置清理完成` | | `{ "status": "cleanup-failed" }` | `⚠️ Phase 5 後置清理未完成 — 殘留:{回傳的 remaining 內容}` | ⛔ **這一行必須依 Executor 的實際回傳決定,不得憑印象或推定寫入。** ⛔ **這一行必須輸出,且必須是整段回覆的最後一行。** > **該行缺席時的判讀(給閱讀回覆的人,非給本 Orchestrator)**:狀態行未出現在可見回覆**不等於**流程未完成。缺席時一律**以磁碟為準**:檢查 `{testProjectDir}/.orchestrator/` 是否已整個消失。 --- ## 執行進度顯示規範 ### 各階段必要輸出 | 動作時機 | 必輸出文字 | |---------|----------| | 啟動 Analyzer **前** | `## 階段 1:啟動分析(Analyzer)` | | Analyzer 回傳後 | `✅ 階段 1 完成 — 識別出 N 個方法、Y 個依賴、Z 個場景` | | 啟動 Writer **前** | `## 階段 2:啟動撰寫(Test Writer)` | | Writer 回傳後 | `✅ 階段 2 完成 — 已建立測試檔案,共 N 個測試案例` | | 啟動 Executor **前** | `## 階段 3:啟動執行(Test Executor)` | | Executor 回傳後 | `✅ 階段 3 完成 — N 個測試案例通過,修正 Y 次` | | 啟動 Reviewer **前** | `## 階段 4:啟動審查(Test Reviewer)` | | Reviewer 回傳後 | `✅ 階段 4 完成` | | **結果呈現後** | 執行 `report` 指令並**把其 stdout 的兩張表格(Token 用量、各階段耗時)貼進回覆**(⛔ 只跑不貼 = 未完成) | | **Token 表格之後**(真正最後一步)| 執行 Phase 5 後置清理,並輸出其狀態行 | --- ## 結果整合與呈現 收到四個 subagent 的回傳結果後,你必須整合呈現給使用者: ### 必呈現的內容 1. **測試檔案連結**:列出 Writer 產出的測試檔案路徑。**不需在 chat 中嵌入完整測試程式碼** 2. **執行結果摘要**:Executor 以 `dotnet run` 執行的結果(通過/失敗/略過數、修正輪數);`buildResult` 不是 `success` 時明說「未通過建置」 3. **品質審查摘要**:Reviewer 的 `overallScore` 和關鍵 `issues`。`overallScore` 為 `upstream-build-blocked` 時明說「建置未通過,未給評分」 4. **改善建議**(如果有的話):Reviewer 的 `missingTestCases` 和 severity=warning 以上的問題 5. **Writer 的技術選擇**:列出 `skillsLoaded`,以及 `deviations`(偏離預設做法的項目與理由)。**`deviations` 為空時也必須明說「未偏離預設做法」** 6. **Executor 修正紀錄**(如果有的話) 7. **範圍摘要**:呈現 `requestedScope` 與 `excludedMethods` ——「未涵蓋而排除:{excludedMethods}」,`[]` 時明說「被測類別的公開方法全數納入」。採用模式另加一句「本次採用使用者提供的場景,涵蓋方法:{adoptedMethods}」 8. **`.csproj` 變動**:彙整所有 Writer 回傳的 `nugetChanges` 逐筆列出。**即使為空也必須明說「`.csproj` 未變動」** 9. **生產程式碼觀察**:呈現 Executor/Reviewer 回傳的 `productionObservations[]`。本流程**不修改 `src/`**;有觀察時逐筆列出並**等使用者決定**,沒有時明說「未發現生產程式碼問題」
عرض على GitHub
ملف SKILL.md هذا كبير جدا، لذلك يعرض SkillsMP القسم الاول فقط هنا. عرض على GitHub