{"id":"5f30c461-bcca-49b5-ba69-c72284f085e9","shortId":"QKhs5R","kind":"skill","title":"dotnet-testing-advanced-tunit-fundamentals","tagline":"TUnit 新世代測試框架入門完整指南。當需要使用 TUnit 建立測試專案或從 xUnit 遷移至 TUnit 時使用。涵蓋 Source Generator 驅動測試發現、AOT 編譯支援、流暢式非同步斷言。包含專案建立、[Test] 屬性、生命週期管理、並行控制與 xUnit 語法對照。\nMake sure to use this skill whenever the user mentions TUnit, Source Generator testing, AOT test framework, TUnit vs xUnit, or migra","description":"# TUnit 新世代測試框架入門基礎\n\n## TUnit 框架核心特色\n\n### 1. Source Generator 驅動的測試發現\n\nTUnit 與傳統測試框架最大的差異在於使用 Source Generator 在**編譯時期**完成測試發現，避免反射成本、完全支援 Native AOT、更快的啟動時間。\n\n```csharp\n// TUnit 在編譯時期就透過 Source Generator 產生測試註冊程式碼\npublic class ModernTests\n{\n    [Test] // 編譯時期就被處理和最佳化\n    public async Task TestMethod()\n    {\n        await Assert.That(true).IsTrue();\n    }\n}\n```\n\n### 2. AOT (Ahead-of-Time) 編譯支援\n\n```text\n傳統 JIT：C# 原始碼 → IL 中間碼 → 執行時期 JIT 編譯 → 機器碼 → 執行\nAOT：    C# 原始碼 → 編譯時期直接產生 → 機器碼 → 直接執行\n```\n\nAOT 優勢：超快啟動時間、更小的記憶體占用、可預測的效能、更適合容器化部署。大型專案可達 10-30 倍啟動時間改善。\n\n### 3. Microsoft.Testing.Platform 採用\n\nTUnit 建構在微軟最新的 Microsoft.Testing.Platform 之上，而非傳統的 VSTest 平台。\n\n**重要注意事項：** TUnit 專案**不需要**也**不應該**安裝 `Microsoft.NET.Test.Sdk` 套件。\n\n### 4. 預設並行執行\n\nTUnit 將並行執行設為預設，需要時可用 `[NotInParallel(\"GroupName\")]` 控制特定測試群組依序執行。\n\n## TUnit 專案建立\n\n支援手動建立（console 模板 + TUnit 套件）或使用 TUnit Template（`dotnet new tunit`，推薦）。專案需設定 csproj（TUnit 套件、IsTestProject）與 GlobalUsings.cs。所有測試方法**必須是非同步的**（`async Task`）。\n\n> 完整專案建立步驟與 csproj 範例請參閱 [references/project-setup.md](references/project-setup.md)\n\n## 測試屬性與參數化\n\n### 基本測試 [Test]\n\nTUnit 統一使用 `[Test]` 屬性，不像 xUnit 區分 `[Fact]` 和 `[Theory]`：\n\n```csharp\n[Test]\npublic async Task Add_輸入1和2_應回傳3()\n{\n    var calculator = new Calculator();\n    var result = calculator.Add(1, 2);\n    await Assert.That(result).IsEqualTo(3);\n}\n```\n\n### 參數化測試 [Arguments]\n\n```csharp\n[Test]\n[Arguments(1, 2, 3)]\n[Arguments(-1, 1, 0)]\n[Arguments(0, 0, 0)]\npublic async Task Add_多組輸入_應回傳正確結果(int a, int b, int expected)\n{\n    var calculator = new Calculator();\n    var result = calculator.Add(a, b);\n    await Assert.That(result).IsEqualTo(expected);\n}\n```\n\n## TUnit.Assertions 斷言系統\n\nTUnit 採用流暢式（Fluent）斷言設計，所有斷言都是非同步的。支援相等性、布林值、數值比較、字串、集合、例外等多種斷言，並可透過 `And` / `Or` 組合條件。\n\n```csharp\nawait Assert.That(actual).IsEqualTo(expected);\nawait Assert.That(email).Contains(\"@\").And.EndsWith(\".com\");\nawait Assert.That(() => action()).Throws<InvalidOperationException>();\n```\n\n> 完整斷言類型與範例請參閱 [references/tunit-assertions-detail.md](references/tunit-assertions-detail.md)\n\n## 測試生命週期管理\n\nTUnit 支援建構式 / `Dispose` 模式，以及 `[Before(Test)]`、`[Before(Class)]`、`[After(Test)]`、`[After(Class)]` 等屬性。\n\n```text\n執行順序：Before(Class) → 建構式 → Before(Test) → 測試方法 → After(Test) → Dispose → After(Class)\n```\n\n> 完整生命週期範例與屬性對照表請參閱 [references/lifecycle-management.md](references/lifecycle-management.md)\n\n## 並行執行控制與 xUnit 遷移\n\nTUnit 預設並行執行所有測試，使用 `[NotInParallel]` 控制特定群組依序執行。提供完整的 xUnit → TUnit 語法對照表、遷移範例、CLI 執行指令與 IDE 整合設定。\n\n> 完整並行控制、語法對照與遷移範例請參閱 [references/xunit-migration.md](references/xunit-migration.md)\n\n## 效能比較\n\n| 場景             | xUnit   | TUnit   | TUnit AOT | 效能提升  |\n| ---------------- | ------- | ------- | --------- | --------- |\n| **簡單測試執行** | 1,400ms | 1,000ms | 60ms      | 23x (AOT) |\n| **非同步測試**   | 1,400ms | 930ms   | 26ms      | 54x (AOT) |\n| **並行測試**     | 1,425ms | 999ms   | 54ms      | 26x (AOT) |\n\n## 常見問題與解決方案\n\n1. **套件相容性** — 移除 `Microsoft.NET.Test.Sdk`，TUnit 使用新的測試平台\n2. **IDE 整合問題** — 確認 IDE 版本支援 Microsoft.Testing.Platform，啟用相關預覽功能\n3. **非同步斷言遺忘** — 所有斷言都需要 `await`，測試方法必須是 `async Task`\n\n## 適用場景評估\n\n### 適合使用 TUnit\n\n1. **全新專案**：沒有歷史包袱\n2. **效能要求高**：大型測試套件（1000+ 測試）\n3. **技術棧先進**：使用 .NET 8+，計劃採用 AOT\n4. **CI/CD 重度使用**：測試執行時間直接影響部署頻率\n5. **容器化部署**：快速啟動時間很重要\n\n### 暫時不建議\n\n1. **Legacy 專案**：已有大量 xUnit 測試\n2. **保守團隊**：需要穩定性勝過創新性\n3. **複雜測試生態**：大量使用 xUnit 特定套件\n4. **舊版 .NET**：還在 .NET 6/7\n\n## 輸出格式\n\n- 產生 TUnit 測試類別（含 [Test]、[Arguments] 屬性）\n- 產生 .csproj 設定（TUnit 套件參考）\n- 提供 GlobalUsings.cs 設定\n- 包含 xUnit 到 TUnit 的遷移程式碼對照\n\n## 參考資源\n\n### 原始文章\n\n本技能內容提煉自「老派軟體工程師的測試修練 - 30 天挑戰」系列文章：\n\n- **Day 28 - TUnit 入門 - 下世代 .NET 測試框架探索**\n  - 鐵人賽文章：https://ithelp.ithome.com.tw/articles/10377828\n  - 範例程式碼：https://github.com/kevintsengtw/30Days_in_Testing_Samples/tree/main/day28\n\n### 官方資源\n\n- [TUnit 官方網站](https://tunit.dev/)\n- [TUnit GitHub](https://github.com/thomhurst/TUnit)\n- [從 xUnit 遷移指南](https://tunit.dev/docs/migration/xunit)\n\n### Microsoft 官方文件\n\n- [Microsoft.Testing.Platform 介紹](https://learn.microsoft.com/dotnet/core/testing/microsoft-testing-platform-intro)\n- [原生 AOT 部署](https://learn.microsoft.com/zh-tw/dotnet/core/deploying/native-aot)\n\n### 相關技能\n\n- `dotnet-testing-advanced-tunit-advanced` - TUnit 進階功能\n- `dotnet-testing-advanced-xunit-upgrade-guide` - xUnit 升級指南\n- `dotnet-testing-xunit-project-setup` - xUnit 專案設定（比較用）","tags":["dotnet","testing","advanced","tunit","fundamentals","agent","skills","kevintsengtw","agent-skills","ai-assisted-development","copilot-skills","csharp"],"capabilities":["skill","source-kevintsengtw","skill-dotnet-testing-advanced-tunit-fundamentals","topic-agent-skills","topic-ai-assisted-development","topic-copilot-skills","topic-csharp","topic-dotnet","topic-dotnet-testing","topic-github-copilot","topic-integration-testing","topic-testing","topic-unit-testing","topic-xunit"],"categories":["dotnet-testing-agent-skills"],"synonyms":[],"warnings":[],"endpointUrl":"https://skills.sh/kevintsengtw/dotnet-testing-agent-skills/dotnet-testing-advanced-tunit-fundamentals","protocol":"skill","transport":"skills-sh","auth":{"type":"none","details":{"cli":"npx skills add kevintsengtw/dotnet-testing-agent-skills","source_repo":"https://github.com/kevintsengtw/dotnet-testing-agent-skills","install_from":"skills.sh"}},"qualityScore":"0.461","qualityRationale":"deterministic score 0.46 from registry signals: · indexed on github topic:agent-skills · 23 github stars · SKILL.md body (4,296 chars)","verified":false,"liveness":"unknown","lastLivenessCheck":null,"agentReviews":{"count":0,"score_avg":null,"cost_usd_avg":null,"success_rate":null,"latency_p50_ms":null,"narrative_summary":null,"summary_updated_at":null},"enrichmentModel":"deterministic:skill-github:v1","enrichmentVersion":1,"enrichedAt":"2026-04-24T13:02:25.576Z","embedding":null,"createdAt":"2026-04-18T23:04:19.471Z","updatedAt":"2026-04-24T13:02:25.576Z","lastSeenAt":"2026-04-24T13:02:25.576Z","tsv":"'-1':227 '-30':124 '/)':493 '/articles/10377828':483 '/docs/migration/xunit)':504 '/dotnet/core/testing/microsoft-testing-platform-intro)':511 '/kevintsengtw/30days_in_testing_samples/tree/main/day28':487 '/thomhurst/tunit)':498 '/zh-tw/dotnet/core/deploying/native-aot)':517 '0':229,231,232,233 '000ms':359 '1':56,211,223,228,356,358,364,371,378,402,425 '10':123 '1000':408 '2':91,212,224,384,405,431 '23x':361 '26ms':367 '26x':375 '28':474 '3':126,217,225,392,410,434 '30':470 '4':145,417,439 '400ms':357,365 '425ms':372 '5':421 '54ms':374 '54x':368 '6/7':444 '60ms':360 '8':414 '930ms':366 '999ms':373 'action':291 'actual':280 'add':201,237 'advanc':4,522,524,530 'ahead':94 'ahead-of-tim':93 'and.endswith':287 'aot':20,44,70,92,110,116,353,362,369,376,416,513 'argument':219,222,226,230,451 'assert.that':88,214,256,279,284,290 'async':84,176,199,235,397 'await':87,213,255,278,283,289,395 'b':243,254 'c':101,111 'calcul':205,207,247,249 'calculator.add':210,252 'ci/cd':418 'class':79,305,309,314,323 'cli':340 'com':288 'consol':156 'contain':286 'csharp':72,196,220,277 'csproj':168,179,454 'day':473 'dispos':299,321 'dotnet':2,163,520,528,537 'dotnet-testing-advanced-tunit-advanc':519 'dotnet-testing-advanced-tunit-fundament':1 'dotnet-testing-advanced-xunit-upgrade-guid':527 'dotnet-testing-xunit-project-setup':536 'email':285 'expect':245,259,282 'fact':193 'fluent':264 'framework':46 'fundament':6 'generat':18,42,58,63,76 'github':495 'github.com':486,497 'github.com/kevintsengtw/30days_in_testing_samples/tree/main/day28':485 'github.com/thomhurst/tunit)':496 'globalusings.cs':173,459 'groupnam':151 'guid':533 'ide':342,385,388 'il':103 'int':240,242,244 'isequalto':216,258,281 'istestproject':171 'istru':90 'ithelp.ithome.com.tw':482 'ithelp.ithome.com.tw/articles/10377828':481 'jit':100,106 'learn.microsoft.com':510,516 'learn.microsoft.com/dotnet/core/testing/microsoft-testing-platform-intro)':509 'learn.microsoft.com/zh-tw/dotnet/core/deploying/native-aot)':515 'legaci':426 'make':30 'mention':39 'microsoft':505 'microsoft.net.test.sdk':143,381 'microsoft.testing.platform':127,131,390,507 'migra':51 'moderntest':80 'nativ':69 'net':413,441,443,478 'new':164,206,248 'notinparallel':150,333 'project':540 'public':78,83,198,234 'references/lifecycle-management.md':325,326 'references/project-setup.md':181,182 'references/tunit-assertions-detail.md':294,295 'references/xunit-migration.md':346,347 'result':209,215,251,257 'setup':541 'skill':35 'skill-dotnet-testing-advanced-tunit-fundamentals' 'sourc':17,41,57,62,75 'source-kevintsengtw' 'sure':31 'task':85,177,200,236,398 'templat':162 'test':3,24,43,45,81,185,188,197,221,303,307,317,320,450,521,529,538 'testmethod':86 'text':98,311 'theori':195 'throw':292 'time':96 'topic-agent-skills' 'topic-ai-assisted-development' 'topic-copilot-skills' 'topic-csharp' 'topic-dotnet' 'topic-dotnet-testing' 'topic-github-copilot' 'topic-integration-testing' 'topic-testing' 'topic-unit-testing' 'topic-xunit' 'true':89 'tunit':5,7,10,14,40,47,52,54,60,73,129,137,147,153,158,161,165,169,186,262,297,330,337,351,352,382,401,447,456,464,475,489,494,523,525 'tunit.assertions':260 'tunit.dev':492,503 'tunit.dev/)':491 'tunit.dev/docs/migration/xunit)':502 'upgrad':532 'use':33 'user':38 'var':204,208,246,250 'vs':48 'vstest':134 'whenev':36 'xunit':12,28,49,191,328,336,350,429,437,462,500,531,534,539,542 '下世代':477 '不像':190 '不應該':141 '不需要':139 '並可透過':273 '並行執行控制與':327 '並行控制與':27 '並行測試':370 '中間碼':104 '之上':132 '也':140 '介紹':508 '以及':301 '使用':332,412 '使用新的測試平台':383 '例外等多種斷言':272 '保守團隊':432 '倍啟動時間改善':125 '傳統':99 '優勢':117 '入門':476 '全新專案':403 '到':463 '包含':461 '包含專案建立':23 '區分':192 '升級指南':535 '原始文章':467 '原始碼':102,112 '原生':512 '參數化測試':218 '參考資源':466 '可預測的效能':120 '含':449 '和':194 '啟用相關預覽功能':391 '在':64 '在編譯時期就透過':74 '執行':109 '執行指令與':341 '執行時期':105 '執行順序':312 '基本測試':184 '場景':349 '多組輸入':238 '大型專案可達':122 '大型測試套件':407 '大量使用':436 '天挑戰':471 '套件':144,159,170 '套件參考':457 '套件相容性':379 '字串':270 '安裝':142 '完全支援':68 '完成測試發現':66 '完整並行控制':344 '完整專案建立步驟與':178 '完整斷言類型與範例請參閱':293 '完整生命週期範例與屬性對照表請參閱':324 '官方文件':506 '官方網站':490 '官方資源':488 '容器化部署':422 '將並行執行設為預設':148 '專案':138,427 '專案建立':154 '專案設定':543 '專案需設定':167 '屬性':25,189,452 '已有大量':428 '布林值':268 '常見問題與解決方案':377 '平台':135 '建構在微軟最新的':130 '建構式':315 '建立測試專案或從':11 '從':499 '必須是非同步的':175 '快速啟動時間很重要':423 '應回傳3':203 '應回傳正確結果':239 '或使用':160 '所有斷言都是非同步的':266 '所有斷言都需要':394 '所有測試方法':174 '技術棧先進':411 '採用':128 '採用流暢式':263 '控制特定測試群組依序執行':152 '控制特定群組依序執行':334 '推薦':166 '提供':458 '提供完整的':335 '支援建構式':298 '支援手動建立':155 '支援相等性':267 '效能提升':354 '效能比較':348 '效能要求高':406 '整合問題':386 '整合設定':343 '數值比較':269 '新世代測試框架入門基礎':53 '新世代測試框架入門完整指南':8 '斷言系統':261 '斷言設計':265 '時使用':15 '暫時不建議':424 '更小的記憶體占用':119 '更快的啟動時間':71 '更適合容器化部署':121 '本技能內容提煉自':468 '框架核心特色':55 '模式':300 '模板':157 '機器碼':108,114 '比較用':544 '沒有歷史包袱':404 '流暢式非同步斷言':22 '涵蓋':16 '測試':409,430 '測試執行時間直接影響部署頻率':420 '測試屬性與參數化':183 '測試方法':318 '測試方法必須是':396 '測試框架探索':479 '測試生命週期管理':296 '測試類別':448 '版本支援':389 '特定套件':438 '生命週期管理':26 '產生':446,453 '產生測試註冊程式碼':77 '當需要使用':9 '的遷移程式碼對照':465 '直接執行':115 '相關技能':518 '確認':387 '移除':380 '等屬性':310 '範例程式碼':484 '範例請參閱':180 '簡單測試執行':355 '系列文章':472 '組合條件':276 '統一使用':187 '編譯':107 '編譯支援':21,97 '編譯時期':65 '編譯時期就被處理和最佳化':82 '編譯時期直接產生':113 '老派軟體工程師的測試修練':469 '而非傳統的':133 '與':172 '與傳統測試框架最大的差異在於使用':61 '舊版':440 '複雜測試生態':435 '計劃採用':415 '設定':455,460 '語法對照':29 '語法對照與遷移範例請參閱':345 '語法對照表':338 '超快啟動時間':118 '輸入1和2':202 '輸出格式':445 '進階功能':526 '適合使用':400 '適用場景評估':399 '遷移':329 '遷移指南':501 '遷移範例':339 '遷移至':13 '避免反射成本':67 '還在':442 '部署':514 '重度使用':419 '重要注意事項':136 '鐵人賽文章':480 '集合':271 '需要時可用':149 '需要穩定性勝過創新性':433 '非同步斷言遺忘':393 '非同步測試':363 '預設並行執行':146 '預設並行執行所有測試':331 '驅動測試發現':19 '驅動的測試發現':59","prices":[{"id":"8c2a192b-4d6c-464a-bbdf-9c0896a1b524","listingId":"5f30c461-bcca-49b5-ba69-c72284f085e9","amountUsd":"0","unit":"free","nativeCurrency":null,"nativeAmount":null,"chain":null,"payTo":null,"paymentMethod":"skill-free","isPrimary":true,"details":{"org":"kevintsengtw","category":"dotnet-testing-agent-skills","install_from":"skills.sh"},"createdAt":"2026-04-18T23:04:19.471Z"}],"sources":[{"listingId":"5f30c461-bcca-49b5-ba69-c72284f085e9","source":"github","sourceId":"kevintsengtw/dotnet-testing-agent-skills/dotnet-testing-advanced-tunit-fundamentals","sourceUrl":"https://github.com/kevintsengtw/dotnet-testing-agent-skills/tree/main/skills/dotnet-testing-advanced-tunit-fundamentals","isPrimary":false,"firstSeenAt":"2026-04-18T23:04:19.471Z","lastSeenAt":"2026-04-24T13:02:25.576Z"}],"details":{"listingId":"5f30c461-bcca-49b5-ba69-c72284f085e9","quickStartSnippet":null,"exampleRequest":null,"exampleResponse":null,"schema":null,"openapiUrl":null,"agentsTxtUrl":null,"citations":[],"useCases":[],"bestFor":[],"notFor":[],"kindDetails":{"org":"kevintsengtw","slug":"dotnet-testing-advanced-tunit-fundamentals","github":{"repo":"kevintsengtw/dotnet-testing-agent-skills","stars":23,"topics":["agent-skills","ai-assisted-development","copilot-skills","csharp","dotnet","dotnet-testing","github-copilot","integration-testing","testing","unit-testing","xunit"],"license":"mit","html_url":"https://github.com/kevintsengtw/dotnet-testing-agent-skills","pushed_at":"2026-03-31T07:28:56Z","description":"AI Agent Skills for .NET Testing - Based on 30-Day Testing Challenge (iThome Ironman 2025 Winner)","skill_md_sha":"c0fd186b559b73fe78a1f8b840cc7319037b30ea","skill_md_path":"skills/dotnet-testing-advanced-tunit-fundamentals/SKILL.md","default_branch":"main","skill_tree_url":"https://github.com/kevintsengtw/dotnet-testing-agent-skills/tree/main/skills/dotnet-testing-advanced-tunit-fundamentals"},"layout":"multi","source":"github","category":"dotnet-testing-agent-skills","frontmatter":{"name":"dotnet-testing-advanced-tunit-fundamentals","description":"TUnit 新世代測試框架入門完整指南。當需要使用 TUnit 建立測試專案或從 xUnit 遷移至 TUnit 時使用。涵蓋 Source Generator 驅動測試發現、AOT 編譯支援、流暢式非同步斷言。包含專案建立、[Test] 屬性、生命週期管理、並行控制與 xUnit 語法對照。\nMake sure to use this skill whenever the user mentions TUnit, Source Generator testing, AOT test framework, TUnit vs xUnit, or migrating to TUnit, even if they don't explicitly ask for TUnit fundamentals.\nKeywords: TUnit, tunit testing, source generator testing, AOT testing, 新世代測試框架, [Test], [Arguments], TUnit.Assertions, Assert.That, Before(Test), After(Test), NotInParallel, TUnit.Templates, Microsoft.Testing.Platform, TUnit vs xUnit, 並行執行"},"skills_sh_url":"https://skills.sh/kevintsengtw/dotnet-testing-agent-skills/dotnet-testing-advanced-tunit-fundamentals"},"updatedAt":"2026-04-24T13:02:25.576Z"}}