系列:從鐵人賽到 Agent Orchestration — AI 自動建立 .NET 測試的完整方案(7)
前言
前幾篇介紹了 Unit Test Orchestrator 的架構設計和實戰流程,以及 v2.0.0 的改進內容與後續方向。單元測試只是測試金字塔的一層,在實際專案中,整合測試同樣重要。
Integration Test Orchestrator 是原本計畫中就要做的第二個 Orchestrator。架構上參考 Unit Test Orchestrator 的 1 + 4 Subagent 設計,流程與各個 Subagent 的內容則依據 dotnet-testing-agent-skills 中的 dotnet-testing-advanced-* 整合測試相關 Skills 來做設計。整合測試面對的挑戰跟單元測試完全不同——Docker 容器管理、DbContext 註冊衝突、API 端點分析、WebApplicationFactory 設定——這些都需要對應的專屬設計。
為什麼需要單獨的 Integration Test Orchestrator
整合測試 vs. 單元測試的根本差異
| 面向 | 單元測試 | 整合測試 |
|---|---|---|
| 分析對象 | Class 的方法 | API 端點 |
| 依賴處理 | Mock 介面 | 真實服務 + 容器 |
| 環境需求 | 無 | Docker、資料庫容器 |
| 基礎設施 | 簡單的 Test Class | WebApplicationFactory、Collection Fixture、TestBase |
| 資料庫 | 不涉及 | DbContext 註冊、連線字串替換 |
| 執行前檢查 | 無 | Docker daemon 是否啟動 |
無法共用的原因
整合測試需要的 Agent 能力完全不同:
- Analyzer 需要分析 API 端點而非 Class 方法、偵測 DbContext 註冊模式、評估容器需求
- Writer 需要透過 mcp-local-rag 語意查詢整合測試專屬的 Skills(
dotnet-testing-advanced-aspnet-integration-testing、dotnet-testing-advanced-testcontainers-database等)、處理 DbContext 註冊衝突、管理 NuGet 套件 - Executor 需要在 Build 之前先檢查 Docker 環境、處理容器啟動等待時間
- Reviewer 需要審查容器管理品質、API 測試特有的品質維度
這些差異不是微調就能解決的,需要完整的重新設計。
Integration Orchestrator 架構
5 個專屬 Agent 定義檔
5 個 Agent 定義檔都放在 .github/agents/ 目錄下:
.github/agents/
├── dotnet-testing-advanced-integration-orchestrator.agent.md
├── dotnet-testing-advanced-integration-analyzer.agent.md
├── dotnet-testing-advanced-integration-writer.agent.md
├── dotnet-testing-advanced-integration-executor.agent.md
└── dotnet-testing-advanced-integration-reviewer.agent.md架構對比
沿用同樣的 1 + 4 Subagent 架構,但管理的 Skills 不同:

Writer 使用的整合測試 Skills
Integration Writer 透過 mcp-local-rag 語意查詢取得 4 個整合測試專屬的 Skills:
| Skill | 用途 |
|---|---|
dotnet-testing-advanced-aspnet-integration-testing | ASP.NET Core 整合測試(WebApplicationFactory) |
dotnet-testing-advanced-webapi-integration-testing | WebAPI 整合測試(HTTP 端點測試) |
dotnet-testing-advanced-testcontainers-database | Testcontainers 資料庫(SQL Server、PostgreSQL) |
dotnet-testing-advanced-testcontainers-nosql | Testcontainers NoSQL(Redis、MongoDB) |
JSON 交接機制
v2.0.0 引入了結構化 JSON 交接機制,各 Subagent 的中間結果不再透過 prompt 傳遞,而是寫入本地檔案,下游 Subagent 直接讀檔:
.orchestrator/{TargetName}/
├── analyzer-result.json # Analyzer 的分析報告
├── writer-result.json # Writer 的輸出摘要
└── executor-result.json # Executor 的執行結果(固定 schema)這讓每個階段的 prompt 保持精簡,不會因為 handoff 文字累積而膨脹。
Orchestrator 的運作機制
在多次驗證迭代後,Integration Orchestrator 積累了幾個重要的運作機制:
分階段委派判斷
當 Analyzer 回傳的 suggestedTestScenarios 超過 15 個時,Orchestrator 會自動將 Writer 委派拆為兩次 — 第一次只建立基礎設施(GlobalUsings、WebApiFactory、IntegrationTestBase、.csproj 更新),第二次才撰寫測試案例。這是因為測試案例數量過多時,Writer 若試圖在單次回應中產出所有檔案,會超出 LLM 輸出 token 上限而截斷。
多目標支援
當使用者一次指定多個 Controller 時,Orchestrator 會對每個目標分別執行完整的四階段流程。Analyzer 和 Writer 可以平行執行(各目標獨立),但 Executor 必須循序執行(避免同專案 dotnet build 並行衝突與容器 port 衝突)。
執行進度顯示
每次委派 subagent 前,Orchestrator 會輸出明顯的階段標題(如 ## 階段 1:委派分析(Integration Analyzer)),收到回傳後輸出過渡摘要再進入下一階段,讓使用者清楚掌握執行進度。
Production Code Bug 發現
整合測試的核心價值之一是發現 Production Code 中的真實 Bug。當 Executor 回報修正了 Production Code(非測試程式碼),Orchestrator 會在最終結果中特別標記此發現 — 這是整合測試 ROI 的直接證明。
Phase Timing
v2.0.0 在 Orchestrator 中內建了階段耗時記錄,每次完整流程結束後會輸出 integration-orchestrator-timing.log,顯示各階段耗時:
Phase 1 (Analyzer): xx 秒
Phase 2 (Writer): x 分 xx 秒
Phase 3 (Executor): xx 秒
Phase 4 (Reviewer): xx 秒
─────────────────────
Total: x 分 xx 秒四個 Subagent 的差異比較
Analyzer 差異
整合測試的 Analyzer 與單元測試版本有根本性的不同:
| 面向 | Unit Test Analyzer | Integration Analyzer |
|---|---|---|
| 分析對象 | Class 的建構子和方法 | API 端點(Controller Action) |
| 分類維度 | Service / Validator / Legacy | API 架構類型(Minimal API / Controller) |
| 依賴分析 | 介面注入、TimeProvider | DbContext、容器需求、Middleware |
| 特殊分析 | Complex Model、IFileSystem | DbContext 註冊模式、Type 衝突風險 |
| 環境偵測 | — | TargetFramework、testFramework(projectContext) |
DbContext 註冊模式分析
這是我在開發 Integration Orchestrator 時踩過最大的坑,也是 Analyzer 最關鍵的新增能力。它會分析 Program.cs 中 DbContext 的註冊方式,分為三種模式:
| 模式 | 說明 | 風險程度 |
|---|---|---|
hardcoded-unconditional | 直接 AddDbContext 沒有條件判斷 | 高 — 會與測試的 DbContext 註冊衝突 |
conditional | 有 if 條件判斷環境 | 低 — 測試可以用不同環境繞過 |
no-registration | Program.cs 中沒有註冊 DbContext | 無風險 |
這個分析結果會直接影響 Writer 的 DbContext 衝突處理策略。
Type 衝突風險分析
當專案使用 Redis 等外部套件時,可能會有 Type 名稱衝突的風險(例如 StackExchange.Redis.Order 與業務 Model Order)。Analyzer 會掃描並標記這些潛在衝突,讓 Writer 在撰寫時使用完整的 namespace 避免問題。
目標專案環境偵測
Analyzer 在分析初期會自動偵測目標專案的 TargetFramework(如 net8.0、net9.0、net10.0),並將測試框架固定為 xunit。這個資訊會寫入 projectContext 欄位,確保下游 Writer 使用正確的版本號,不會因 LLM 記憶偏差而寫入錯誤的框架版本。
輸出格式
Integration Analyzer 的 JSON 報告比單元測試版本多了幾個關鍵欄位:
{
"endpointsToTest": [...],
"dbContextInfo": {
"hasDbContext": true,
"dbContextName": "AppDbContext",
"provider": "SqlServer"
},
"dbRegistrationAnalysis": {
"pattern": "hardcoded-unconditional",
"riskLevel": "high"
},
"containerRequirements": {
"sqlServer": true,
"redis": false
},
"typeConflictRisks": [...],
"requiredSkills": [
"dotnet-testing-advanced-webapi-integration-testing",
"dotnet-testing-advanced-testcontainers-database"
],
"suggestedTestScenarios": [
"GetOrders_資料庫有訂單資料_應回傳200OK與訂單清單",
"CreateOrder_輸入有效訂單_應回傳201Created",
"CreateOrder_輸入無效訂單_應回傳400BadRequest與驗證錯誤"
],
"projectContext": {
"targetFramework": "net9.0",
"testFramework": "xunit",
"solutionPath": "...",
"sourceProjectPath": "...",
"testProjectPath": "..."
}
}Writer 差異
Integration Writer 面對的複雜度遠高於單元測試版本。
DbContext 衝突處理 — 三種策略
根據 Analyzer 分析的 DbContext 註冊模式,Writer 選擇不同的處理策略:
| Analyzer 偵測結果 | Writer 策略 | 處理方式 |
|---|---|---|
hardcoded-unconditional | Strategy A | 修改 Program.cs 加入環境條件判斷 + 在測試的 ConfigureServices 中替換 |
conditional | Strategy B | 直接在測試的 ConfigureServices 中 AddDbContext |
no-registration | Strategy C | 直接在測試的 ConfigureServices 中 AddDbContext |
Strategy A 是最複雜的情況,也是開發過程中讓我頭痛最久的問題。當 Program.cs 中有 hardcoded-unconditional 的 DbContext 註冊時,如果測試也嘗試註冊 DbContext,就會發生 DB Provider 衝突 — 兩個 Provider 打架,測試直接爆掉。Writer 的處理方式是:
// Program.cs 中加入環境條件判斷
if (!builder.Environment.IsEnvironment("Testing"))
{
builder.Services.AddDbContext<AppDbContext>(options =>
options.UseSqlServer(connectionString));
}測試基礎設施建立
Integration Writer 除了撰寫測試外,還需要建立完整的測試基礎設施:
TestProject/
├── Fixtures/
│ └── WebApiFactory.cs # WebApplicationFactory 封裝
├── TestBase/
│ └── IntegrationTestBase.cs # 測試基底類別
├── Collections/
│ └── IntegrationTestCollection.cs # Collection Fixture
└── Controllers/
└── OrdersControllerTests.cs # 測試類別NuGet 套件版本適配
Writer 在撰寫前會執行 dotnet list package --outdated 查詢可升級套件版本。版本決定邏輯:SKILL.md 中的版本號是「最低保證版本」,.csproj 既有版本同樣是版本下限,兩者取較高值,再根據查詢結果升級至同主版號最新穩定版本。禁止 major 升級、禁止降版、禁止使用未經確認的版本號。新增套件後還會二次查詢,確保新增套件也套用相同的升級邏輯。
InMemory 專用 Factory 模式
當 containerRequirements 為空(純 InMemory 測試)時,Writer 會建立簡化版 Factory — 不需要 IAsyncLifetime、不需要 Container 欄位,僅設定 UseEnvironment("Testing")。資料庫初始化由 IntegrationTestBase 的 CleanupDatabaseAsync() 負責。
11 條撰寫規範
Integration Writer 有自己的 11 條撰寫規範,與單元測試的 12 條規範不完全相同:
- AAA + Cleanup Pattern(測試後清理資料庫)
- 中文三段式命名
- 使用 AwesomeAssertions(包含
.Be200Ok()等 Web 專用斷言,不得使用不存在的.HaveStatusCode()) - 使用 WebApplicationFactory(不得
new HttpClient()或直接建立TestServer) - Collection Fixture 共享容器
- 資料庫清理策略(DatabaseManager + Respawn 或
ExecuteSqlRaw手動清理,依載入的 SKILL 決定) - 使用
System.Net.Http.Json(PostAsJsonAsync、ReadFromJsonAsync) - ProblemDetails 驗證(使用
Satisfy<T>()鏈式語法,含複合欄位驗證錯誤與邊界 Happy Path 回應體驗證) - 移除不必要的 using
- 測試隔離(每個測試獨立,透過 IntegrationTestBase 清理)
- 對稱驗證覆蓋(含條件驗證規則的
null與空字串邊界對稱)
Executor 差異
Integration Executor 最大的差異在於 Step 0:Docker 環境檢查。執行完成後,Executor 會將結果寫入 .orchestrator/{TargetName}/executor-result.json(固定 schema,包含 totalTests、passedTests、failedTests 等欄位),供 Reviewer 讀取。

特殊的錯誤修正模式
Integration Executor 除了編譯錯誤和測試失敗外,還需要處理容器相關的錯誤:
| 錯誤類型 | 常見原因 | 修正方式 |
|---|---|---|
| Docker daemon 未啟動 | Docker Desktop 沒開 | 回報使用者,請求啟動 Docker |
| Port 衝突 | 容器 Port 被佔用 | 使用隨機 Port |
| DB Provider 衝突 | DbContext 重複註冊 | 修改 Program.cs 加入條件判斷 |
| DI 容器例外 | 服務註冊衝突 | 調整 ConfigureServices 順序 |
| JSON 序列化失敗 | API 回傳格式不符預期 | 使用 System.Net.Http.Json |
修改 Production Code 的授權
這是一個我猶豫了很久的設計決策。Integration Executor 有兩種被授權修改 Production Code 的情境:
- DB Provider 衝突修正 — 當
Program.cs有hardcoded-unconditional的 DbContext 註冊,導致測試環境與正式環境的 DB Provider 打架時,Executor 被授權修改Program.cs加入IsEnvironment("Testing")環境條件判斷。這在 Unit Test Executor 中是不被允許的。 - Production Code Bug 修正 — 當整合測試因 Production Code 缺陷而失敗(例如 Controller 未注入已存在的 Validator、缺少必要的 middleware 註冊等),Orchestrator 會授權 Executor 修正 Production Code。此類修正必須在回傳結果中明確標記為「Production Code Bug 修正」,與一般測試程式碼修正區分。
這些授權都是受限的 — 不是讓 Executor 任意修改 Production Code,而是針對整合測試揭露的特定問題給予精確的修正權限。
Executor Fast-Path
與 Unit Test Orchestrator 一致,v2.0.0 在 Integration Executor 中同樣加入了 happy-path 快返規則:首輪 build 成功且 filtered tests 全數通過時,立即回傳固定 schema 的精簡 JSON,不再進行多餘的後置審視步驟。
Reviewer 差異
Integration Reviewer 在原有的六大審查維度基礎上,增加了整合測試特有的面向:
| 審查維度 | Unit Test Reviewer | Integration Reviewer |
|---|---|---|
| 命名品質 | ✅ 中文三段式 | ✅ 中文三段式 |
| 斷言品質 | AwesomeAssertions | AwesomeAssertions + .Be200Ok() 等 Web 斷言 |
| 測試結構 | AAA Pattern | AAA + Cleanup Pattern |
| 程式碼品質 | unused using | unused using + System.Net.Http.Json + Factory 封裝性 |
| Mock 品質 | NSubstitute | N/A(整合測試不 Mock) |
| 覆蓋率 | 方法覆蓋 | 端點覆蓋 + 驗證規則對稱覆蓋 + 條件驗證邊界對稱 |
| 容器管理 | — | ConfigureServices 模式、Container 初始化、WaitStrategy |
新增的「容器管理」審查維度包含:
ConfigureServices是否正確 — 支援兩種合法模式:(A)SingleOrDefaultdescriptor 移除後重新註冊、(B) Program.cs 環境條件判斷 +UseEnvironment("Testing")直接AddDbContext。不得使用ConfigureTestServices- Container 是否正確初始化和釋放(
readonly欄位直接初始化,非 nullable) - 是否有適當的 WaitStrategy(等待容器就緒),不得使用
Task.Delay()硬式等待 - Factory 封裝性 — 所有 Factory 類型(含 InMemory)均不得暴露
public EnsureCreatedAsync()方法 - 目錄結構 — 測試專案必須有
Fixtures/、TestBase/、Controllers/(或Endpoints/)子目錄結構 UseEnvironment("Testing")—ConfigureWebHost中必須呼叫
DbContext 衝突處理實例
這是整合測試中最常遇到的問題。以 SQL Server Testcontainers 場景為例:
問題:Program.cs 中有 hardcoded-unconditional 的 DbContext 註冊,測試也嘗試註冊 DbContext 指向 Testcontainers,導致 DB Provider 衝突。
Analyzer 偵測:
{
"dbRegistrationAnalysis": {
"pattern": "hardcoded-unconditional",
"riskLevel": "high",
"location": "Program.cs:12"
}
}Writer 套用 Strategy A:修改 Program.cs 加入環境條件判斷,測試中設定 Testing 環境。
Executor 驗證:Build 通過、Test 通過,無 DB Provider 衝突。
這個問題在開發初期就被識別和解決,後續的場景都自動套用正確的策略。
dotnet-testing-advanced-integration-orchestrator - 執行狀態
以下是有開啟 dotnet-testing-skills MCP (mcp-local-rag) 的執行結果




兩個 Orchestrator 的完整對比
| 面向 | Unit Test Orchestrator | Integration Orchestrator |
|---|---|---|
| Agent 定義檔 | 5 個 dotnet-testing-*.agent.md | 5 個 dotnet-testing-advanced-integration-*.agent.md |
| 管理的 Skills | 29 個 Skills(透過 mcp-local-rag 查詢) | 4 個整合測試 Skills(透過 mcp-local-rag 查詢) |
| Analyzer 分析對象 | Class 方法 | API 端點 |
| Analyzer 特殊分析 | Complex Model、IFileSystem | DbContext 註冊模式、Type 衝突 |
| Writer 基礎設施 | 簡單 Test Class | WebApiFactory、Collection Fixture、TestBase |
| Executor Step 0 | — | Docker 環境檢查 |
| Executor 修改 Production Code | 不允許 | 授權(DB Provider 衝突 + Production Code Bug 修正) |
| Reviewer 特殊維度 | — | 容器管理審查 |
四個 Orchestrator 的定位
Integration Orchestrator 是 4 個 Orchestrator 中的第二個,每個都沿用 1 + 4 Subagent 架構,但管理不同的 Skills 集合:
| Orchestrator | 測試領域 | 載入的 Skills | 狀態 |
|---|---|---|---|
| Unit Test Orchestrator | 單元測試 | 29 個 Skills(透過 mcp-local-rag 查詢)+ dotnet-test | ✅ 驗證完成 |
| Integration Orchestrator | 整合測試 | 4 個整合測試 Skills(透過 mcp-local-rag 查詢) | ✅ 本篇 |
| Aspire Testing Orchestrator | Aspire 測試 | dotnet-testing-advanced-aspire-testing(透過 mcp-local-rag 查詢) | ✅ 驗證完成 |
| TUnit Testing Orchestrator | TUnit 測試 | dotnet-testing-advanced-tunit-*(2 個 Skills,透過 mcp-local-rag 查詢) | ✅ 驗證完成 |
後兩個 Orchestrator 會在接下來的兩篇分別介紹。
小結
回顧 Integration Orchestrator 的開發過程,最大的體會是:整合測試的複雜度不是「單元測試 + Docker」這麼簡單。DbContext 註冊衝突、Type 名稱衝突、容器管理、對稱驗證覆蓋 — 每一個都是獨立的設計問題,需要在 Agent 定義中明確處理。
經過多次驗證迭代,Agent 定義檔也持續演進 — 加入了分階段委派判斷避免 LLM 輸出截斷、NuGet 版本適配邏輯防止版本偏差、InMemory 專用 Factory 模式簡化無容器場景、以及 Production Code Bug 發現機制。這些都是在實戰中踩坑後回饋到 Agent 定義的改善。
好消息是,1 + 4 Subagent 的架構模式被證明是可以「複製」的。單元測試和整合測試用同樣的架構骨架,但各自填入不同的領域知識。接下來的兩篇會介紹 Aspire Testing Orchestrator 和 TUnit Testing Orchestrator — 同樣的架構模式,但面對截然不同的測試技術。
參考資源
- dotnet-testing-agent-orchestration:https://github.com/kevintsengtw/dotnet-testing-agent-orchestration
- Integration Orchestrator 設計文件:https://github.com/kevintsengtw/dotnet-testing-agent-orchestration/blob/main/docs/agent_orchestration/dotnet-testing-advanced-integration-orchestrator.md
- 整合測試操作指南:https://github.com/kevintsengtw/dotnet-testing-agent-orchestration/blob/main/docs/agent_orchestration/practice-guide-integration-testing.md
- 整合測試驗證專案:https://github.com/kevintsengtw/dotnet-testing-agent-orchestration/tree/main/samples/practice_integration
- dotnet-testing-agent-skills:https://github.com/kevintsengtw/dotnet-testing-agent-skills
純粹是在寫興趣的,用寫程式、寫文章來抒解工作壓力