Integration、Aspire、TUnit — 三個進階 Orchestrator 使用指南
Integration、Aspire、TUnit 三個進階 Orchestrator 一次看完。它們與 Unit 系出同源、共用 1+4 架構,差別在 Docker 容器、分散式環境與框架執行方式 — 本文聚焦各自的觸發方式、前置需求與該注意的特性。
前言
上一篇把安裝走了一遍,也完整介紹了 Unit Test Orchestrator 的使用。這一篇接著處理其餘三個 — Integration、Aspire、TUnit。
它們跟 Unit Test 系出同源:同一套 1 + 4 架構、同樣的 Analyzer → Writer → Executor → Reviewer 四階段、同樣透過斜線指令觸發、同樣的 JSON 交接與計時 Hook。安裝基礎也完全共用(上一篇已經講過)。所以這篇不重複四階段流程的通則,把重點放在每個 Orchestrator 各自在做哪一種測試、以及那種測試天生會多出來的講究。
跟 Unit 比,多出來的是什麼
在進到三個 Orchestrator 之前,先把它們相對 Unit Test 多出來的東西講清楚,後面三節就不必各自重複一遍。
主要是三件事。第一是執行環境:Integration 與 Aspire 都要起真實的資料庫容器,所以需要 Docker;Unit 與 TUnit 不用。第二是測試載體:Unit 直接 new 出待測類別,Integration 用 WebApplicationFactory 把整個 WebAPI 跑起來、再用 Testcontainers 起資料庫,Aspire 則換成 DistributedApplicationTestingBuilder,把整個分散式應用一起拉起來。第三是測試框架:前三個都用 xUnit、跑 dotnet test,TUnit 是另一套框架,連執行方式都不一樣。
所以接下來三節,分別看 Integration 怎麼用真實環境測一整條鏈路、Aspire 怎麼把整個分散式應用組起來測、TUnit 這個不同框架的工作流程長什麼樣。
一、Integration Test Orchestrator — 為 WebAPI 做端對端整合測試
觸發指令是 /dotnet-testing-orchestrator-integration,它要處理的是 ASP.NET Core WebAPI 的整合測試:不是把相依 mock 掉、單獨測一個類別,而是把整個 API 跑起來,從 HTTP 請求一路測到商業邏輯、再到資料庫,驗證一整條鏈路真的串得起來。技術棧是 WebApplicationFactory + Testcontainers + Respawn + AwesomeAssertions,資料層支援 InMemory、PostgreSQL、SQL Server、MongoDB、Redis 五種。
用真實資料庫,還是用 InMemory
因為要測真實鏈路,Docker Desktop 必須是執行中的狀態 — Testcontainers 靠 Docker Engine 起資料庫容器,沒開的話 Executor 會在 Phase 3 直接回報錯誤、停下流程。唯一的例外是 EF Core 的 InMemory Provider,它不碰 Docker,適合只想快速驗證端點路由與商業邏輯的情況。
所以實務上會分兩種下法。只想確認 CRUD 端點通不通,用 InMemory 最快:
/dotnet-testing-orchestrator-integration 為 OrdersController 撰寫整合測試。
被測試 API:src/MyApp.WebApi
測試專案:tests/MyApp.WebApi.Tests/MyApp.WebApi.Tests.csproj
OrdersController 有 8 個端點(CRUD + Confirm/Cancel),使用 EF Core InMemory。要驗證得靠真實資料庫行為才測得出來的東西(唯一鍵約束、重複建立的錯誤回應、交易),就改用 Testcontainer,Analyzer 會自動偵測 SQL Server 依賴並產生對應的容器設定:
/dotnet-testing-orchestrator-integration 為 OrdersController 撰寫整合測試。
被測試 API:src/MyApp.WebApi
測試專案:tests/MyApp.WebApi.Tests/MyApp.WebApi.Tests.csproj
資料庫:SQL Server Testcontainers,需測試唯一鍵約束與重複建立訂單的錯誤回應。測試失敗時,Executor 可能會去動 Production Code
這是 Integration 跟 Unit 在執行階段最不一樣的地方,而它其實是「端對端」這個定位的自然結果。單元測試失敗,問題幾乎一定在測試或被測類別本身;但整合測試是把整條鏈路串起來跑,失敗的根因可能落在 Production Code — 路由設定錯了、少註冊一個 Validator 的 DI、驗證邏輯回了錯的 HTTP 狀態碼。
所以 Integration 的 Executor 被授權在這種情況下直接修正 Production Code,並且會在結果報告裡明確標記成「Production Code Bug 修正」,讓你知道哪些非測試的檔案被動過。授權是有界線的:它可以改路由、補 DI 註冊、修正回應狀態碼這類「接線」層級的問題,但不會去改業務邏輯、加新功能或動資料庫 Schema。Unit Test 的 Executor 則完全不碰 Production Code。
實際跑下來,這一段是我覺得最值得盯著看的 — 它等於把「測試紅了到底是誰的問題」這個判斷攤開給你看。報告裡會固定有一節「Production Code Bug 修正」:沒動到就是「無」,動了就列出改過的檔案(後面「實際跑一次」會看到這一節)。
一個容易卡住的地方:Redis 型別撞名
整合測試的坑大多跟環境有關(Docker 沒開、image 拉不下來),這些看錯誤訊息就知道怎麼解。比較隱蔽的是 Redis 的命名衝突:當你的 domain model 有個型別叫 Order,而 StackExchange.Redis 命名空間下剛好也有同名型別,編譯就會撞在一起。Writer 產生測試時會自動在 GlobalUsings.cs 加一行 alias 解決,但如果你是自己手寫測試遇到,記得補上 global using RedisOrder = StackExchange.Redis.Order;。
實際跑一次:OrdersController
把前面說的綜合起來,看一次真實的 Integration 跑完長什麼樣。這裡用練習專案的 OrdersController(8 個端點,PostgreSQL + FluentValidation)當例子,走真實資料庫容器這條路:
/dotnet-testing-orchestrator-integration 為 OrdersController 撰寫整合測試。
被測試 API:samples/integration/practice_integration/src/Practice.Integration.WebApi
測試專案:samples/integration/practice_integration/tests/Practice.Integration.WebApi.Tests/Practice.Integration.WebApi.Tests.csproj
OrdersController 有 8 個端點(CRUD + Confirm/Cancel),使用 PostgreSQL + FluentValidation。觸發後一樣先做 Phase 0 清理,確認沒有殘留,再進入階段 1,把 Analyzer 派出去分析 Controller 的端點結構。

階段 1 跑完,Analyzer 認出 8 個端點、20 個測試情境,判斷需要 PostgreSQL 容器與三個整合測試相關的 Skill。這裡冒出一個跟 Unit 不一樣的地方:因為情境數偏多(20 個,超過門檻),Integration 的 Writer 不是切成兩個平行 Writer,而是分兩趟跑 — 第一趟先把測試的基礎設施搭好(WebApplicationFactory、測試基底、Respawn 的資料庫管理、Collection Fixture),第二趟才寫實際的測試案例。

兩趟 Writer 寫完(基礎設施約 2 分 47 秒、測試案例約 2 分 2 秒,合計 23 個案例),進入階段 3。Executor 讀進剛產出的 OrdersWebApplicationFactory 等檔案,開始建置與執行。

這次 Docker 是開著的,建置一次就過、23 個測試全數通過、零修正輪次,接著進入階段 4 的 Reviewer。

Reviewer 跑完給出完整報告。開頭先列出產出的測試檔案 — 整合測試特有的那幾個基礎設施檔都在:OrdersWebApplicationFactory、Respawn 的 DatabaseManager、IntegrationTestBase、Collection Fixture。執行摘要也把環境寫得很清楚:Docker Desktop 可用、Testcontainers PostgreSQL(postgres:16-alpine)+ Respawn 清理、23 / 23 全過。

品質審查的部分,正面點出測試全用了 AwesomeAssertions.Web 的語法(Be200Ok、Be404NotFound、Be409Conflict)、容器架構(Collection Fixture + Respawn)正確;改善建議則分中、低優先,列出還缺哪些邊界測試(像是電子郵件為空的 400、Notes 長度邊界)。

報告裡固定有一節「Production Code Bug 修正」,正好呼應前面講的那個授權 — 這次因為建置一次就過、測試也全綠,所以是「無」,報告還順手說明了為什麼沒衝突(Program.cs 用 if (!IsEnvironment("Testing")) 把資料庫 DI 包了起來)。真的遇到接線層級的 bug 時,這一欄就會列出被動過的 Production Code 檔案。下面那張「各階段耗時」表一樣是計時 Hook 的產物,這次整體約 10 分鐘 — 比 Unit 那次久,因為要真的把容器拉起來、等它就緒。

最後 Phase 5 把整個 .orchestrator/ 暫存刪掉,只留下測試程式碼。

二、Aspire Testing Orchestrator — 為 Aspire 分散式應用做整合測試
觸發指令是 /dotnet-testing-orchestrator-aspire。它跟上一個一樣是在做整合測試,差別在受測的對象是一個 .NET Aspire 分散式應用。這個差別決定了它跟 Integration Orchestrator 最根本的分界:Integration 是由測試程式碼自己用 Testcontainers 一個個把容器宣告、起起來;Aspire 則把這件事交給應用自己的 AppHost — 測試用 DistributedApplicationTestingBuilder 直接把整個 AppHost 跑起來,由 Aspire 照 AppHost 裡的宣告去編排所有 Resource(資料庫、快取、各個服務)。
觸發時要多給 AppHost
也因為環境是 AppHost 在編排,觸發時就多了一個 Unit/Integration 都沒有的參數 — AppHost 路徑。Aspire 的 Analyzer 要讀 AppHost 的 Program.cs,才能認出整個分散式應用的 Resource 拓撲:哪些是 SQL Server、哪些是 Redis、哪些是 Project。
/dotnet-testing-orchestrator-aspire 為 BookingsController 撰寫 Aspire 整合測試。
被測試 API:src/MyApp.Aspire.WebApi
AppHost:src/MyApp.Aspire.AppHost
測試專案:tests/MyApp.Aspire.AppHost.Tests/MyApp.Aspire.AppHost.Tests.csproj
BookingsController 使用 SQL Server(BookingsDb)+ Redis(cache)。
需涵蓋 Happy Path 與錯誤路徑(FluentValidation 400、404)。把需求講清楚,Writer 會把 Happy Path 與各種錯誤路徑(FluentValidation 400、404、409 衝突)連同端對端情境一起涵蓋進測試案例,對應整個分散式應用的各條路徑。
執行階段的幾個特性
Aspire 的 Executor 比 Integration 多一道檢查:除了確認 Docker,還要確認環境能建置 Aspire 應用。傳統上這代表要裝 .NET Aspire workload,不過 Aspire 9.x 之後改用 Aspire.AppHost.Sdk NuGet 套件 — AppHost 專案只要引用了這個 SDK 就能建置,不一定要另外裝 workload(後面實際跑的那次,就是 workload 未裝、靠 SDK 套件通過檢查的)。兩者都沒有時,再補裝 workload:
dotnet workload install aspire
dotnet workload list # 確認 aspire 已列出因為一次要把整個分散式環境拉起來、等所有服務 health check 通過才開始跑測試案例,這種測試本來就會比一般整合測試花更久,Executor 的 timeout 也設得比較長,不會因為啟動慢就誤判逾時。這是它的常態,不是出問題。
也因為跑一輪的成本比較高,這裡有一個其他三組沒有的取捨:如果 Executor 第一次就全數通過、零修正輪次,Orchestrator 可以選擇跳過 Reviewer。Unit/Integration 是一律會進 Reviewer 的;Aspire 在首次全綠時省下這一步,是合理的權衡。當然,只要中間有修正過,還是會照常 review。
最容易踩的坑:Resource 名稱要對齊
Aspire 測試裡呼叫 app.CreateHttpClient("bookingapi") 用的名稱,必須跟 AppHost Program.cs 裡 AddProject<...>("bookingapi") 宣告的名稱完全一致,差一個字,執行時就會冒出 Resource 'xxx' not found。Writer 會自動對齊,但你手改測試時務必確認這兩處字串相同 — 這是 Aspire 專屬、又最常見的一個坑。
實際跑一次:BookingsController
同樣完整跑一次給你看。這裡用練習專案的 Aspire 應用,被測對象是 BookingsController(9 個端點,背後是 SQL Server + Redis)。跟前兩個最大的不同,是指令裡要多給 AppHost 路徑:
/dotnet-testing-orchestrator-aspire 為 BookingsController 撰寫 Aspire 整合測試。
被測試 API:samples/aspire/practice_aspire/src/Practice.Aspire.WebApi
AppHost:samples/aspire/practice_aspire/src/Practice.Aspire.AppHost
測試專案:samples/aspire/practice_aspire/tests/Practice.Aspire.AppHost.Tests/Practice.Aspire.AppHost.Tests.csproj
BookingsController 有 9 個端點(CRUD + Confirm/CheckIn/Cancel 狀態轉換 + ByStatus 查詢),使用 SQL Server(BookingsDb)+ Redis(cache)。Phase 0 清理後進入階段 1。Aspire 的 Analyzer 不是只讀 Controller,而是去讀 AppHost 的 Program.cs,認出整個分散式應用的 Resource 拓撲。

階段 1 跑完(花了 3 分 11 秒,比 Integration 久),Analyzer 認出 9 個端點、29 個測試情境、3 個 Resource(sql、BookingsDb、cache),還記下了服務名稱 bookingapi — 這個名字等一下會很關鍵。接著啟動 Writer。

Writer 寫完(3 分 40 秒),產出一個測試類別,加上四個基礎設施檔(AspireAppFixture、Collection 定義、測試基底、Respawn 的 DatabaseManager)與 GlobalUsings,共 29 個案例,進入階段 3。

這次 Executor 跑了一輪修正 — 測試專案少了對 WebApi 的 ProjectReference、也少了 StackExchange.Redis 套件,編譯報 CS0234/CS0246,Executor 自己補上後重跑,29 個測試全數通過。因為中間修正過,這次 Reviewer 就不會被跳過 — 前面提到 Aspire 只有在「首次全綠、零修正」時才會省略 Reviewer,這裡正好是反例。

Reviewer 給出 4 / 5 的評級、零 FAIL、覆蓋率 100%,接著進入 Phase 5 把整個 .orchestrator/ 清掉。

完整報告開頭列出產出的檔案 — Aspire 特有的 AspireAppFixture(用 DistributedApplicationTestingBuilder 啟動 AppHost)、Respawn 的 DatabaseManager、Collection 定義都在。這裡有個值得一提的細節:報告寫著「Aspire workload 未安裝,但 AppHost 採用 Aspire.AppHost.Sdk 套件,符合例外條件」,正好印證前面說的 — Aspire 9.x 靠 SDK 套件就能建置,不一定要裝 workload。

品質審查的正面肯定裡,有一條剛好印證前面那個最容易踩的坑 — Reviewer 確認了測試裡 CreateHttpClient("bookingapi") 跟 AppHost AddProject(...)("bookingapi") 的名稱一致。改善建議則列了 7 條 WARN(像是 400 測試沒驗 Title、[Collection] 重複宣告、容器清理沒設 ContainerLifetime.Session),都屬可選的強化。

最後是這次的修正紀錄與各階段耗時表。整體跑了 11 分 6 秒,是三種整合測試裡最久的(Analyzer 跟 Writer 各超過 3 分鐘)— 把整個分散式應用拉起來本來就慢,這是常態,不是出問題。

三、TUnit Testing Orchestrator — TUnit 版的測試工作流程
觸發指令是 /dotnet-testing-orchestrator-tunit。它做的事情跟 Unit Test 一樣,是同一條「分析 → 撰寫 → 執行 → 審查」的流程、產出測試;唯一的不同是目標框架換成了 TUnit。而 TUnit 跟 xUnit 不只是 attribute 名稱不同,它是基於 Roslyn Source Generator、在編譯時產生測試發現程式碼的框架,這個底層差異會一路影響到測試專案怎麼設定、怎麼執行。
框架不一樣,產出和執行就不一樣
最直接的影響有三個。測試專案必須是 OutputType = Exe(而非類別庫)— 因為 Source Generator 會替它產生 Main 進入點,測試專案實際上是一個可執行檔,也因此它不需要 Docker,這點跟 Unit 一樣。執行用 dotnet run 而不是 dotnet test,這是四個 Orchestrator 裡唯一一個 Executor 用 dotnet run 的。還有,TUnit 的斷言是非同步 API,所有測試方法都是 async Task。
新建測試是它最常態的用法,例如替一個純函式類別用 [Test] + [Arguments] 做參數化:
/dotnet-testing-orchestrator-tunit
目標:src/MyApp.Core/Services/BookCatalog.cs
說明:純函式書籍目錄類別,使用 [Test] + [Arguments] 參數化測試
測試專案:tests/MyApp.Core.Tests/MyApp.Core.Tests.csproj也能把 xUnit 測試遷移過來
除了新建,它還支援一個進階場景:把現有的 xUnit 測試遷移成 TUnit。下法是多給一個遷移來源:
/dotnet-testing-orchestrator-tunit
目標:CatalogExportService(含 xUnit → TUnit 遷移)
遷移來源:migration_source/BookCatalogXunitTests.cs
被測試目標:src/MyApp.Core/Services/CatalogExportService.cs
測試專案:tests/MyApp.Core.Tests/MyApp.Core.Tests.csproj
說明:將現有 xUnit 測試遷移到 TUnit,並補充新測試。遷移時 Writer 會做語法轉換:[Fact] 轉成 [Test]、[Theory] + [InlineData] 轉成 [Test] + [Arguments]、constructor 轉成 [Before(Test)]、IDisposable.Dispose 轉成 [After(Test)]、Assert.Equal 轉成 await Assert.That(...).IsEqualTo(...)。遷移情境下 Reviewer 還會特別做一次「零殘留驗證」— 檢查 [Fact]、[Theory]、[InlineData]、[MemberData]、ITestOutputHelper、using Xunit; 這些 xUnit 痕跡是不是都清乾淨了,有殘留會被回報出來。
兩個 TUnit 特有的陷阱
一個是 decimal 參數。[Arguments] 不支援 decimal 字面量,[Arguments(1.5m)] 會直接編譯錯誤;遇到含 decimal 的測試參數,Writer 會自動改用 [MethodDataSource] 透過靜態方法提供資料,你手寫時也要這樣換。
另一個更隱蔽:忘記 await。TUnit 的 Assert.That 是非同步的,漏掉 await 的話斷言根本不會執行,測試會永遠通過、但其實什麼都沒驗到。寫 TUnit 測試時,確認每個 Assert.That 前面都有 await。
實際跑一次:BookCatalog
最後也跑一次 TUnit 給你看。被測對象是練習專案裡的 BookCatalog(6 個純函式靜態方法),下這個指令:
/dotnet-testing-orchestrator-tunit 為 BookCatalog 撰寫 TUnit 測試。
被測試目標:samples/tunit/practice_tunit/src/Practice.TUnit.Core/Services/BookCatalog.cs
測試專案:samples/tunit/practice_tunit/tests/Practice.TUnit.Core.Tests/Practice.TUnit.Core.Tests.csproj
BookCatalog 是純函式類別(6 個靜態方法),適合使用 [Test] + [Arguments] 參數化測試。Phase 0 清理後進入階段 1,Analyzer 分析這個類別。

階段 1 認出 6 個方法、20 個測試場景,純函式無依賴,只需要 tunit-fundamentals 一個 Skill。因為方法數 6 > 5,這裡跟 Unit 一樣觸發 Writer 平行分割 — 用 greedy 分組分成兩組、兩個 Writer 同時寫,靠 partial class BookCatalogTests 讓兩邊最後併成同一個類別、不會衝突。

兩個 Writer 寫完,產出 BookCatalogTests.cs 與 BookCatalogTests.More.cs,進入階段 3。Executor 一上來 dotnet build 就碰到編譯錯誤(Exit code 1),開始自己修。

修好之後改用 dotnet run 執行測試(這就是 TUnit 跟其他三組最不一樣的地方 — 它是可執行檔,不是 dotnet test),測試全數通過。這一輪一共修了兩次,第二次正好就是前面講的那個 decimal 陷阱:[Arguments] 不能放 decimal 字面值(CS0182),Executor 自動改成 [MethodDataSource]。

Reviewer 給 4 / 5、60 / 60 通過,TUnit 合規性完全過關(OutputType=Exe、沒有 Microsoft.NET.Test.Sdk、所有 [Test] 都是 async Task、沒有 xUnit 殘留)。報告的執行結果區把這次的兩次修正寫得很清楚 — 一個是方法名稱裡的 % 字元(C# 識別碼不允許),一個就是 decimal 那個。

改善建議列了 8 條(像是 [MethodDataSource] 的方法忘了加 static、DateTime.Today 造成的 flaky 風險),使用的 Skill 就只有 tunit-fundamentals 一個。各階段耗時表顯示整體跑了 6 分 39 秒 — 比兩個要起容器的整合測試快不少,跟 Unit 差不多,畢竟 TUnit 一樣不用 Docker。

最後 Phase 5 把 .orchestrator/ 交接目錄清掉,流程結束。

附帶一提:三個工作流程跟 Copilot 版的耗時對照
跟上一篇 Unit Test 一樣,這三個工作流程我先前也在 GitHub Copilot 版(dotnet-testing-agent-orchestration v2.0.0)跑過,兩個版本都會輸出分階段耗時,這裡也各放一次來對照。
一樣要先打預防針:這不是控制變因的 benchmark。平台與模型不同(Claude 版跑在 Claude Code、底層是 Claude;Copilot v2.0.0 版跑在 GitHub Copilot、底層是 GPT-5.3-Codex),被測對象與環境也各有差異(下面每組會註明)。各只跑一次,數字會隨當下負載跳動,看個量級就好。
Integration(Claude 版:OrdersController + PostgreSQL Testcontainers;Copilot v2.0.0:同樣是 OrdersController,但用 InMemory)
| 階段 | Claude 版 | Copilot v2.0.0 版 |
|---|---|---|
| Analyzer | 1 分 33 秒 | 3 分 27 秒 |
| Writer | 4 分 49 秒 | 7 分 46 秒 |
| Executor | 1 分 12 秒 | 1 分 47 秒 |
| Reviewer | 2 分 45 秒 | 2 分 51 秒 |
| 總計 | 10 分 19 秒 | 16 分 2 秒 |
值得一提的是,Claude 版這次還是用真實 PostgreSQL 容器(要等容器起來)、Copilot v2.0.0 版用的是不碰容器的 InMemory,照理說 InMemory 應該更快,但整體時間仍是 Claude 版這次較短。
Aspire(Claude 版:BookingsController;Copilot v2.0.0:bookingapi,都是 9 個端點、SQL Server + Redis 的同一個練習應用)
| 階段 | Claude 版 | Copilot v2.0.0 版 |
|---|---|---|
| Analyzer | 3 分 11 秒 | 9 分 47 秒 |
| Writer | 3 分 40 秒 | 9 分 45 秒 |
| Executor | 2 分 28 秒 | 16 分 6 秒 |
| Reviewer | 1 分 47 秒 | 3 分 46 秒 |
| 總計 | 11 分 6 秒 | 39 分 24 秒 |
Aspire 這組差距最大 — 兩邊都用 Aspire SDK、也都真的把 SQL Server 與 Redis 容器拉起來,但 Copilot v2.0.0 那次光是 Executor 就花了 16 分鐘。
TUnit(兩邊都是同一個 BookCatalog,6 個純函式靜態方法)
| 階段 | Claude 版 | Copilot v2.0.0 版 |
|---|---|---|
| Analyzer | 1 分 13 秒 | 4 分 19 秒 |
| Writer | 1 分 26 秒 | 3 分 21 秒 |
| Executor | 1 分 52 秒 | 1 分 9 秒 |
| Reviewer | 2 分 8 秒 | 2 分 31 秒 |
| 總計 | 6 分 39 秒 | 11 分 28 秒 |
TUnit 是三組裡被測對象最一致的(同一個類別)。這次 Executor 反而是 Copilot 版略快 — 因為 Claude 版那次踩到了 decimal 與方法名兩個要修的點、多跑了兩輪修正;但 Analyzer 與 Writer 的差距讓總時間還是 Claude 版這次較短。
(Copilot 版數字取自各工作流程 v2.0.0 的 timing log,Claude 版取自前面各自那次走查的各階段耗時表。)
三組看下來,這幾次都是 Claude 版的總時間明顯較短,差距主要落在 Analyzer 與 Writer 這兩個推理與產出階段。不過還是那句話:每組各跑一次、被測對象與環境又不完全相同,這些表看的是量級差異,不是精準跑分。
小結
到這裡,四個 Orchestrator 就全部介紹完了 — 架構解析、安裝與 Unit Test,以及這篇的 Integration、Aspire、TUnit。
回頭看這四個工作流程,它們真的是系出同源:共用同一套安裝基礎、同樣的 1 + 4 架構、同樣的四階段流程與 JSON 交接。差別只在於各自處理的測試領域不同 — Integration 把整個 API 跟真實資料庫跑起來做端對端驗證、還給了 Executor 修正 Production Code 的授權;Aspire 同樣是整合測試,但把整個分散式環境交給 AppHost 編排起來測;TUnit 則換了整個框架與執行方式(Source Generator、OutputType=Exe、dotnet run)。但骨架是一致的,學會其中一個,其他三個只是換個對象、注意各自的前置與特性而已。
一套 1 + 4 的分工架構,搭配一份共用的 dotnet-testing-agent-skills,就能涵蓋從單元測試到分散式應用、從 xUnit 到 TUnit 的各種測試場景 — 架構是共用的模板,真正不同的是填進去的領域知識。
不過,這四個 Orchestrator 背後其實還有一塊沒談:它們與各個 subagent 的定義檔,本質上是一大包 prompt — 這些 prompt 是怎麼被調到現在這個樣子的?
下一篇、也是這個系列的最後一篇,就講這件事:用 autoresearch 把 agent 定義的優化,變成一個可量測、可迭代的過程。
參考資源
- dotnet-testing-agent-orchestration(Claude Code 版):https://github.com/kevintsengtw/dotnet-testing-agent-orchestration-claude
- dotnet-testing-agent-skills:https://github.com/kevintsengtw/dotnet-testing-agent-skills
- Claude Code 官方文件:https://docs.claude.com/en/docs/claude-code/overview
- .NET Aspire 官方文件:https://learn.microsoft.com/dotnet/aspire/
- TUnit 官方文件:https://thomhurst.github.io/TUnit/
純粹是在寫興趣的,用寫程式、寫文章來抒解工作壓力