{"id":"6f93d260-cf8f-4b54-9550-07dc81fd52fb","shortId":"xNnpFr","kind":"skill","title":"dotnet-testing-advanced-xunit-upgrade-guide","tagline":"xUnit 2.9.x 到 3.x 升級完整指南。當需要將 xUnit v2 升級至 v3 或了解 xUnit v3 新功能與破壞性變更時使用。涵蓋套件更新、async void 修正、IAsyncLifetime 調整。包含新功能介紹: Assert.Skip、Explicit Tests、Matrix Theory、Assembly Fixtures。\nMake sure to use this skill whenever the user mentions xUnit upgrade, xUnit v3, xUnit migration, xUn","description":"# xUnit 升級指南：從 2.9.x 到 3.x\n\n## 核心概念\n\n### 套件命名變革\n\nxUnit v3 採用全新的套件命名策略：\n\n| v1~v2 套件名稱              | v3 套件名稱                         | 說明         |\n| --------------------------- | ----------------------------------- | ------------ |\n| `xunit`                     | `xunit.v3`                          | 主要測試框架 |\n| `xunit.assert`              | `xunit.v3.assert`                   | 斷言函式庫   |\n| `xunit.core`                | `xunit.v3.core`                     | 核心元件     |\n| `xunit.abstractions`        | (移除)                              | 不再需要     |\n| `xunit.runner.visualstudio` | `xunit.runner.visualstudio` (3.x.y) | 測試執行器   |\n\n**重要**：使用 `xunit.v3` 套件名稱，不是 `xunit`。\n\n### 最低運行時需求\n\n- **.NET Framework 4.7.2+** 或 **.NET 8.0+** (推薦)\n- **不支援**：.NET Core 3.1、.NET 5/6/7\n\n---\n\n## 破壞性變更\n\n涵蓋 OutputType 改為 Exe、async void 不再支援、IAsyncLifetime 繼承 IAsyncDisposable、SkippableFact 移除、僅支援 SDK-style 專案、自訂 DataAttribute 簽名變更等六項破壞性變更，每項皆附修正前後的程式碼對照。\n\n> 完整破壞性變更清單與程式碼範例請參考 [references/breaking-changes.md](references/breaking-changes.md)\n\n---\n\n## 升級步驟\n\n五步驟 SOP：建立升級分支 → 更新專案檔案（套件、OutputType）→ 修正 async void → 更新 using → 編譯與測試。另含 .NET 10 SDK MTP 模式遷移指南（global.json 設定、CLI 用法變更、VSTest 遷移步驟）。\n\n> 完整升級步驟與 .NET 10 MTP 模式指南請參考 [references/upgrade-steps.md](references/upgrade-steps.md)\n\n---\n\n## xUnit 3.x 新功能\n\n涵蓋 Assert.Skip / SkipUnless / SkipWhen 動態跳過、Explicit Tests、[Test] 屬性、MatrixTheoryData 矩陣測試、Assembly Fixtures、Test Pipeline Startup、多格式測試報告等新功能，每項皆附完整程式碼範例。\n\n> 完整新功能範例請參考 [references/new-features.md](references/new-features.md)\n\n### Testcontainers.XunitV3 整合套件\n\nTestcontainers 官方推出 `Testcontainers.XunitV3`（4.9.0），專為 xUnit v3 設計的整合套件，自動管理容器的建立與銷毀，取代手動實作 `IAsyncLifetime` 的方式。\n\n```xml\n<PackageReference Include=\"Testcontainers.XunitV3\" Version=\"4.9.0\" />\n```\n\n> 若專案同時使用 Testcontainers 與 xUnit v3，建議採用此套件簡化容器生命週期管理。\n\n---\n\n## xunit.runner.json 設定\n\n```json\n{\n  \"$schema\": \"https://xunit.net/schema/v3/xunit.runner.schema.json\",\n  \"parallelAlgorithm\": \"conservative\",\n  \"maxParallelThreads\": 4,\n  \"diagnosticMessages\": true,\n  \"internalDiagnosticMessages\": false,\n  \"methodDisplay\": \"classAndMethod\",\n  \"preEnumerateTheories\": true,\n  \"stopOnFail\": false\n}\n```\n\n---\n\n## 常見問題與解決方案\n\n### 問題 1：找不到 xunit.abstractions\n\n移除 `using Xunit.Abstractions;`，相關類型已移到 `Xunit` 命名空間。\n\n### 問題 2：IDE 無法發現測試\n\n確認 IDE 版本：Visual Studio 2022 17.8+、Rider 2023.3+、VS Code 最新版。如仍有問題，可暫時停用 MTP：\n\n```xml\n<PropertyGroup>\n  <EnableMicrosoftTestingPlatform>false</EnableMicrosoftTestingPlatform>\n</PropertyGroup>\n```\n\n> **.NET 10 SDK 注意**：若使用 MTP 模式，停用 MTP 會導致 `dotnet test` 錯誤。應改為移除 `global.json` 中的 `test` 區段。\n\n---\n\n## 升級檢查清單\n\n### 升級前\n\n- [ ] 確認目標框架版本 (.NET 8+ 或 .NET Framework 4.7.2+)\n- [ ] 檢查專案檔案格式 (SDK-style)\n- [ ] 識別所有 async void 測試方法\n- [ ] 檢查 IAsyncLifetime 實作\n- [ ] 評估相依套件相容性\n- [ ] 建立備份分支\n\n### 升級過程\n\n- [ ] 更新套件參考 (使用 `xunit.v3`)\n- [ ] 移除 `xunit.abstractions` 參考\n- [ ] 修改 OutputType 為 Exe\n- [ ] 修正所有 async void 測試方法\n- [ ] 更新 using 陳述式\n- [ ] 重構自訂屬性 (如有)\n- [ ] 驗證編譯成功\n- [ ] 執行所有測試\n\n### 升級後驗證\n\n- [ ] 功能完整性測試\n- [ ] 效能基準比較\n- [ ] CI/CD Pipeline 驗證\n- [ ] 文檔更新\n- [ ] 團隊培訓\n- [ ] （.NET 10+）設定 `global.json` 啟用 MTP 模式並驗證 `dotnet test` 正常運作\n\n---\n\n## IDE 與工具支援\n\n| IDE           | 最低版本   |\n| ------------- | ---------- |\n| Visual Studio | 2022 17.8+ |\n| VS Code       | 最新版     |\n| Rider         | 2023.3+    |\n\nxUnit 3.x 預設啟用 Microsoft Testing Platform（MTP），搭配 .NET 10 SDK 可使用原生 MTP 模式。\n\n> .NET 10 MTP 模式詳細設定請參考 [references/upgrade-steps.md](references/upgrade-steps.md)\n\n---\n\n## 輸出格式\n\n- 產生升級後的測試專案 .csproj 設定（xunit.v3 套件、OutputType Exe）\n- 包含 async void 修正為 async Task 的測試程式碼\n- 包含 IAsyncLifetime 調整與 SkippableFact 替換範例\n- 產生 xunit.runner.json 設定檔\n\n## 參考資源\n\n### 原始文章\n\n本技能內容提煉自「老派軟體工程師的測試修練 - 30 天挑戰」系列文章：\n\n- **Day 26 - xUnit 升級指南：從 2.9.x 到 3.x 的轉換**\n  - 鐵人賽文章：https://ithelp.ithome.com.tw/articles/10377477\n  - 範例程式碼：https://github.com/kevintsengtw/30Days_in_Testing_Samples/tree/main/day26\n\n### 官方文件\n\n- [xUnit.net 官方網站](https://xunit.net/)\n- [xUnit v3 新功能文件](https://xunit.net/docs/getting-started/v3/whats-new)\n- [xUnit 2.x → 3.x 官方遷移指南](https://xunit.net/docs/getting-started/v3/migration)\n- [xunit.v3 NuGet 套件](https://www.nuget.org/packages/xunit.v3)\n\n### 相關技能\n\n- `dotnet-testing-xunit-project-setup` - xUnit 專案設定基礎\n- `dotnet-testing-advanced-tunit-fundamentals` - TUnit 替代框架\n- `dotnet-testing-advanced-testcontainers-database` - Testcontainers 資料庫整合測試（搭配 XunitV3 套件）","tags":["dotnet","testing","advanced","xunit","upgrade","guide","agent","skills","kevintsengtw","agent-skills","ai-assisted-development","copilot-skills"],"capabilities":["skill","source-kevintsengtw","skill-dotnet-testing-advanced-xunit-upgrade-guide","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-xunit-upgrade-guide","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,315 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.781Z","embedding":null,"createdAt":"2026-04-18T23:04:21.003Z","updatedAt":"2026-04-24T13:02:25.781Z","lastSeenAt":"2026-04-24T13:02:25.781Z","tsv":"'/)':435 '/articles/10377477':425 '/docs/getting-started/v3/migration)':450 '/docs/getting-started/v3/whats-new)':441 '/kevintsengtw/30days_in_testing_samples/tree/main/day26':429 '/packages/xunit.v3)':456 '/schema/v3/xunit.runner.schema.json':220 '1':237 '10':151,163,268,338,370,376 '17.8':256,354 '2':247,443 '2.9':9,58,416 '2022':255,353 '2023.3':258,359 '26':412 '3':12,61,88,169,361,419,445 '3.1':108 '30':408 '4':224 '4.7.2':100,293 '4.9.0':198 '5/6/7':110 '8':289 '8.0':103 'advanc':4,469,477 'assembl':36,183 'assert.skip':31,173 'async':25,116,144,299,319,390,393 'ci/cd':332 'classandmethod':230 'cli':157 'code':260,356 'conserv':222 'core':107 'csproj':383 'dataattribut':130 'databas':479 'day':411 'diagnosticmessag':225 'dotnet':2,277,344,459,467,475 'dotnet-testing-advanced-testcontainers-databas':474 'dotnet-testing-advanced-tunit-fundament':466 'dotnet-testing-advanced-xunit-upgrade-guid':1 'dotnet-testing-xunit-project-setup':458 'exe':115,317,388 'explicit':32,177 'fals':228,234,266 'fixtur':37,184 'framework':99,292 'fundament':471 'github.com':428 'github.com/kevintsengtw/30days_in_testing_samples/tree/main/day26':427 'global.json':155,281,340 'guid':7 'iasyncdispos':121 'iasynclifetim':28,119,205,303,397 'ide':248,251,347,349 'internaldiagnosticmessag':227 'ithelp.ithome.com.tw':424 'ithelp.ithome.com.tw/articles/10377477':423 'json':216 'make':38 'matrix':34 'matrixtheorydata':181 'maxparallelthread':223 'mention':47 'methoddisplay':229 'microsoft':364 'migrat':53 'mtp':153,164,264,272,275,342,367,373,377 'net':98,102,106,109,150,162,267,288,291,337,369,375 'nuget':452 'outputtyp':113,142,315,387 'parallelalgorithm':221 'pipelin':186,333 'platform':366 'preenumeratetheori':231 'project':462 'references/breaking-changes.md':134,135 'references/new-features.md':191,192 'references/upgrade-steps.md':166,167,379,380 'rider':257,358 'schema':217 'sdk':126,152,269,296,371 'sdk-style':125,295 'setup':463 'skill':43 'skill-dotnet-testing-advanced-xunit-upgrade-guide' 'skippablefact':122,399 'skipunless':174 'skipwhen':175 'sop':138 'source-kevintsengtw' 'startup':187 'stoponfail':233 'studio':254,352 'style':127,297 'sure':39 'task':394 'test':3,33,178,179,185,278,283,345,365,460,468,476 'testcontain':195,209,478,480 'testcontainers.xunitv3':193,197 'theori':35 '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':226,232 'tunit':470,472 'upgrad':6,49 'use':41,147,241,323 'user':46 'v1':68 'v2':17 'v3':19,22,51,66,71,201,212,437 'visual':253,351 'void':26,117,145,300,320,391 'vs':259,355 'vstest':159 'whenev':44 'www.nuget.org':455 'www.nuget.org/packages/xunit.v3)':454 'x':10,13,59,62,170,362,417,420,444,446 'x.y':89 'xml':207,265 'xun':54 'xunit':5,8,16,21,48,50,52,55,65,74,96,168,200,211,244,360,413,436,442,461,464 'xunit.abstractions':83,239,242,312 'xunit.assert':77 'xunit.core':80 'xunit.net':219,431,434,440,449 'xunit.net/)':433 'xunit.net/docs/getting-started/v3/migration)':448 'xunit.net/docs/getting-started/v3/whats-new)':439 'xunit.net/schema/v3/xunit.runner.schema.json':218 'xunit.runner.json':214,402 'xunit.runner.visualstudio':86,87 'xunit.v3':75,93,310,385,451 'xunit.v3.assert':78 'xunit.v3.core':81 'xunitv3':483 '~v2':69 '不再支援':118 '不再需要':85 '不支援':105 '不是':95 '中的':282 '主要測試框架':76 '五步驟':137 '使用':92,309 '修改':314 '修正':27,143 '修正所有':318 '修正為':392 '停用':274 '僅支援':124 '到':11,60,418 '功能完整性測試':330 '動態跳過':176 '包含':389,396 '包含新功能介紹':30 '區段':284 '升級前':286 '升級完整指南':14 '升級後驗證':329 '升級指南':56,414 '升級檢查清單':285 '升級步驟':136 '升級至':18 '升級過程':307 '原始文章':405 '參考':313 '參考資源':404 '取代手動實作':204 '另含':149 '可使用原生':372 '可暫時停用':263 '命名空間':245 '問題':236,246 '啟用':341 '團隊培訓':336 '執行所有測試':328 '多格式測試報告等新功能':188 '天挑戰':409 '套件':141,386,453,484 '套件名稱':70,72,94 '套件命名變革':64 '如仍有問題':262 '如有':326 '完整升級步驟與':161 '完整新功能範例請參考':190 '完整破壞性變更清單與程式碼範例請參考':133 '官方推出':196 '官方文件':430 '官方網站':432 '官方遷移指南':447 '實作':304 '專案':128 '專案設定基礎':465 '專為':199 '屬性':180 '常見問題與解決方案':235 '建立備份分支':306 '建立升級分支':139 '建議採用此套件簡化容器生命週期管理':213 '從':57,415 '應改為移除':280 '或':101,290 '或了解':20 '找不到':238 '採用全新的套件命名策略':67 '推薦':104 '搭配':368,482 '改為':114 '效能基準比較':331 '整合套件':194 '文檔更新':335 '新功能':171 '新功能文件':438 '新功能與破壞性變更時使用':23 '斷言函式庫':79 '更新':146,322 '更新套件參考':308 '更新專案檔案':140 '替代框架':473 '替換範例':400 '最低版本':350 '最低運行時需求':97 '最新版':261,357 '會導致':276 '本技能內容提煉自':406 '核心元件':82 '核心概念':63 '模式':273,374 '模式並驗證':343 '模式指南請參考':165 '模式詳細設定請參考':378 '模式遷移指南':154 '檢查':302 '檢查專案檔案格式':294 '正常運作':346 '每項皆附修正前後的程式碼對照':132 '每項皆附完整程式碼範例':189 '注意':270 '涵蓋':112,172 '涵蓋套件更新':24 '測試執行器':90 '測試方法':301,321 '為':316 '無法發現測試':249 '版本':252 '產生':401 '產生升級後的測試專案':382 '用法變更':158 '當需要將':15 '的方式':206 '的測試程式碼':395 '的轉換':421 '相關技能':457 '相關類型已移到':243 '矩陣測試':182 '破壞性變更':111 '確認':250 '確認目標框架版本':287 '移除':84,123,240,311 '範例程式碼':426 '簽名變更等六項破壞性變更':131 '系列文章':410 '編譯與測試':148 '繼承':120 '老派軟體工程師的測試修練':407 '自動管理容器的建立與銷毀':203 '自訂':129 '與':210 '與工具支援':348 '若使用':271 '若專案同時使用':208 '設定':156,215,339,384 '設定檔':403 '設計的整合套件':202 '評估相依套件相容性':305 '說明':73 '調整':29 '調整與':398 '識別所有':298 '資料庫整合測試':481 '輸出格式':381 '遷移步驟':160 '重構自訂屬性':325 '重要':91 '錯誤':279 '鐵人賽文章':422 '陳述式':324 '預設啟用':363 '驗證':334 '驗證編譯成功':327","prices":[{"id":"cc27e007-5d19-4de1-a39d-7c3124d51c2e","listingId":"6f93d260-cf8f-4b54-9550-07dc81fd52fb","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:21.003Z"}],"sources":[{"listingId":"6f93d260-cf8f-4b54-9550-07dc81fd52fb","source":"github","sourceId":"kevintsengtw/dotnet-testing-agent-skills/dotnet-testing-advanced-xunit-upgrade-guide","sourceUrl":"https://github.com/kevintsengtw/dotnet-testing-agent-skills/tree/main/skills/dotnet-testing-advanced-xunit-upgrade-guide","isPrimary":false,"firstSeenAt":"2026-04-18T23:04:21.003Z","lastSeenAt":"2026-04-24T13:02:25.781Z"}],"details":{"listingId":"6f93d260-cf8f-4b54-9550-07dc81fd52fb","quickStartSnippet":null,"exampleRequest":null,"exampleResponse":null,"schema":null,"openapiUrl":null,"agentsTxtUrl":null,"citations":[],"useCases":[],"bestFor":[],"notFor":[],"kindDetails":{"org":"kevintsengtw","slug":"dotnet-testing-advanced-xunit-upgrade-guide","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":"a4a18abc17b0b7ddc62acd6a01b5d3044f76e58b","skill_md_path":"skills/dotnet-testing-advanced-xunit-upgrade-guide/SKILL.md","default_branch":"main","skill_tree_url":"https://github.com/kevintsengtw/dotnet-testing-agent-skills/tree/main/skills/dotnet-testing-advanced-xunit-upgrade-guide"},"layout":"multi","source":"github","category":"dotnet-testing-agent-skills","frontmatter":{"name":"dotnet-testing-advanced-xunit-upgrade-guide","description":"xUnit 2.9.x 到 3.x 升級完整指南。當需要將 xUnit v2 升級至 v3 或了解 xUnit v3 新功能與破壞性變更時使用。涵蓋套件更新、async void 修正、IAsyncLifetime 調整。包含新功能介紹: Assert.Skip、Explicit Tests、Matrix Theory、Assembly Fixtures。\nMake sure to use this skill whenever the user mentions xUnit upgrade, xUnit v3, xUnit migration, xUnit breaking changes, or Assert.Skip, even if they don't explicitly ask for xUnit upgrade guidance.\nKeywords: xunit upgrade, xunit v3, xunit 3.x, xunit migration, xunit 升級, xunit.v3, OutputType Exe, IAsyncLifetime v3, Assert.Skip, SkipUnless, SkipWhen, Explicit attribute, MatrixTheoryData, AssemblyFixture, 破壞性變更"},"skills_sh_url":"https://skills.sh/kevintsengtw/dotnet-testing-agent-skills/dotnet-testing-advanced-xunit-upgrade-guide"},"updatedAt":"2026-04-24T13:02:25.781Z"}}