$npx -y skills add kevintsengtw/dotnet-testing-agent-skills --skill dotnet-testing-xunit-project-setupxUnit 測試專案建立與設定的專門技能。當需要建立測試專案、設定專案結構、配置 NuGet 套件、組織測試資料夾時使用。涵蓋 csproj 設定、套件管理、專案結構、xunit.runner.json 配置等。 Make sure to use this skill whenever the user mentions creating a test project, xUnit setup, project structure for tests, NuGet test packages, or csproj configuration for te
| 1 | # xUnit 測試專案設定指南 |
| 2 | |
| 3 | ## 專案結構最佳實踐 |
| 4 | |
| 5 | ### 建議的解決方案結構 |
| 6 | |
| 7 | ```text |
| 8 | MyProject/ |
| 9 | ├── src/ # 主程式碼目錄 |
| 10 | │ └── MyProject.Core/ |
| 11 | │ ├── MyProject.Core.csproj |
| 12 | │ ├── Calculator.cs |
| 13 | │ ├── Services/ |
| 14 | │ └── Models/ |
| 15 | ├── tests/ # 測試程式碼目錄 |
| 16 | │ └── MyProject.Core.Tests/ |
| 17 | │ ├── MyProject.Core.Tests.csproj |
| 18 | │ ├── CalculatorTests.cs |
| 19 | │ ├── Services/ |
| 20 | │ └── Models/ |
| 21 | └── MyProject.sln |
| 22 | ``` |
| 23 | |
| 24 | **結構原則:** |
| 25 | |
| 26 | 1. **src 與 tests 分離**:清楚區分生產程式碼與測試程式碼 |
| 27 | 2. **命名慣例**:測試專案名稱為 `{主專案名稱}.Tests` |
| 28 | 3. **目錄對應**:測試專案的資料夾結構應對應主專案的結構 |
| 29 | 4. **一對一映射**:每個主專案應有對應的測試專案 |
| 30 | |
| 31 | ## 建立 xUnit 測試專案 |
| 32 | |
| 33 | ### 方法一:使用 .NET CLI(推薦) |
| 34 | |
| 35 | #### 步驟 1:建立解決方案與專案 |
| 36 | |
| 37 | ```powershell |
| 38 | # 建立解決方案 |
| 39 | dotnet new sln -n MyProject |
| 40 | |
| 41 | # 建立主專案(類別庫) |
| 42 | dotnet new classlib -n MyProject.Core -o src/MyProject.Core |
| 43 | |
| 44 | # 建立測試專案(xUnit 範本) |
| 45 | dotnet new xunit -n MyProject.Core.Tests -o tests/MyProject.Core.Tests |
| 46 | |
| 47 | # 將專案加入解決方案 |
| 48 | dotnet sln add src/MyProject.Core/MyProject.Core.csproj |
| 49 | dotnet sln add tests/MyProject.Core.Tests/MyProject.Core.Tests.csproj |
| 50 | |
| 51 | # 建立專案參考(測試專案參考主專案) |
| 52 | dotnet add tests/MyProject.Core.Tests/MyProject.Core.Tests.csproj reference src/MyProject.Core/MyProject.Core.csproj |
| 53 | ``` |
| 54 | |
| 55 | #### 步驟 2:安裝程式碼覆蓋率工具 |
| 56 | |
| 57 | ```powershell |
| 58 | # 切換到測試專案目錄 |
| 59 | cd tests/MyProject.Core.Tests |
| 60 | |
| 61 | # 安裝 coverlet.collector(用於收集程式碼覆蓋率) |
| 62 | dotnet add package coverlet.collector |
| 63 | ``` |
| 64 | |
| 65 | ### 方法二:使用 Visual Studio |
| 66 | |
| 67 | 1. **建立解決方案** |
| 68 | - File → New → Project |
| 69 | - 選擇「Blank Solution」 |
| 70 | - 命名為專案名稱 |
| 71 | |
| 72 | 2. **加入主專案** |
| 73 | - 右鍵解決方案 → Add → New Project |
| 74 | - 選擇「Class Library」 |
| 75 | - 命名為 `MyProject.Core` |
| 76 | |
| 77 | 3. **加入測試專案** |
| 78 | - 右鍵解決方案 → Add → New Project |
| 79 | - 搜尋並選擇「xUnit Test Project」 |
| 80 | - 命名為 `MyProject.Core.Tests` |
| 81 | |
| 82 | 4. **設定專案參考** |
| 83 | - 右鍵測試專案 → Add → Project Reference |
| 84 | - 勾選主專案 |
| 85 | |
| 86 | ## xUnit 測試專案的 csproj 設定 |
| 87 | |
| 88 | ### 標準 xUnit 測試專案 csproj |
| 89 | |
| 90 | 請參考同目錄下的 `templates/xunit-test-project.csproj` 範本檔案。 |
| 91 | |
| 92 | **核心相依套件說明:** |
| 93 | |
| 94 | 1. **xunit**(2.9.3+) |
| 95 | - xUnit 測試框架的核心套件 |
| 96 | - 提供 `[Fact]`、`[Theory]` 等測試屬性 |
| 97 | - 包含 `Assert` 類別與斷言方法 |
| 98 | |
| 99 | 2. **xunit.runner.visualstudio**(3.0.0+) |
| 100 | - Visual Studio Test Explorer 整合 |
| 101 | - 讓測試能在 VS Code、Visual Studio、Rider 中被探索與執行 |
| 102 | - 支援測試結果的即時顯示 |
| 103 | |
| 104 | 3. **Microsoft.NET.Test.Sdk**(18.3.0+) |
| 105 | - .NET 測試平台的 SDK |
| 106 | - 讓 `dotnet test` 指令能夠執行測試 |
| 107 | - 支援測試結果報告與測試探索 |
| 108 | |
| 109 | 4. **coverlet.collector**(8.0.0+) |
| 110 | - 程式碼覆蓋率收集工具 |
| 111 | - 與 `dotnet test` 整合 |
| 112 | - 產生覆蓋率報告(支援 Cobertura、OpenCover 等格式) |
| 113 | |
| 114 | ### 重要 csproj 設定項目 |
| 115 | |
| 116 | ```xml |
| 117 | <PropertyGroup> |
| 118 | <TargetFramework>net9.0</TargetFramework> |
| 119 | <ImplicitUsings>enable</ImplicitUsings> |
| 120 | <Nullable>enable</Nullable> |
| 121 | <IsPackable>false</IsPackable> |
| 122 | <IsTestProject>true</IsTestProject> |
| 123 | </PropertyGroup> |
| 124 | ``` |
| 125 | |
| 126 | **設定說明:** |
| 127 | |
| 128 | - `IsPackable=false`:測試專案不應被打包成 NuGet 套件 |
| 129 | - `IsTestProject=true`:明確標記為測試專案,讓工具識別 |
| 130 | - `Nullable=enable`:啟用可為 Null 的參考型別檢查 |
| 131 | |
| 132 | ## 測試類別基本結構 |
| 133 | |
| 134 | ### 標準測試類別範本 |
| 135 | |
| 136 | ```csharp |
| 137 | namespace MyProject.Core.Tests; |
| 138 | |
| 139 | public class CalculatorTests |
| 140 | { |
| 141 | private readonly Calculator _calculator; |
| 142 | |
| 143 | // 建構函式:每個測試執行前都會被呼叫 |
| 144 | public CalculatorTests() |
| 145 | { |
| 146 | _calculator = new Calculator(); |
| 147 | } |
| 148 | } |
| 149 | ``` |
| 150 | |
| 151 | ### 測試生命週期(重要概念) |
| 152 | |
| 153 | xUnit 的測試隔離機制: |
| 154 | |
| 155 | 1. **每個測試方法都會創建新的測試類別實例** |
| 156 | 2. **建構函式**:在每個測試方法執行前被呼叫 |
| 157 | 3. **測試方法**:執行測試邏輯 |
| 158 | 4. **Dispose()**:如果實作 `IDisposable`,在每個測試方法執行後被呼叫 |
| 159 | |
| 160 | **執行順序範例:** |
| 161 | |
| 162 | ```text |
| 163 | 執行 Test1: |
| 164 | → 建構函式 → Test1 方法 → Dispose() |
| 165 | |
| 166 | 執行 Test2: |
| 167 | → 建構函式 → Test2 方法 → Dispose() |
| 168 | ``` |
| 169 | |
| 170 | 這確保了 **測試隔離**,符合 FIRST 原則的 **I (Independent)**。 |
| 171 | |
| 172 | ## 執行測試 |
| 173 | |
| 174 | ### 使用 .NET CLI |
| 175 | |
| 176 | ```powershell |
| 177 | # 建置專案 |
| 178 | dotnet build |
| 179 | |
| 180 | # 執行所有測試 |
| 181 | dotnet test |
| 182 | |
| 183 | # 執行測試並收集程式碼覆蓋率 |
| 184 | dotnet test --collect:"XPlat Code Coverage" |
| 185 | |
| 186 | # 執行特定測試專案 |
| 187 | dotnet test tests/MyProject.Core.Tests/MyProject.Core.Tests.csproj |
| 188 | |
| 189 | # 執行測試並產生詳細輸出 |
| 190 | dotnet test --verbosity detailed |
| 191 | ``` |
| 192 | |
| 193 | ### 在 IDE 中執行 |
| 194 | |
| 195 | #### VS Code(需安裝 C# Dev Kit) |
| 196 | |
| 197 | 1. 安裝 [C# Dev Kit](https://marketplace.visualstudio.com/items?itemName=ms-dotnettools.csdevkit) |
| 198 | 2. 開啟 Test Explorer(測試總管) |
| 199 | 3. 點擊測試旁的播放按鈕執行 |
| 200 | |
| 201 | #### Visual Studio |
| 202 | |
| 203 | 1. 開啟 Test Explorer(測試 → Test Explorer) |
| 204 | 2. 點擊「Run All」執行所有測試 |
| 205 | 3. 可以右鍵單一測試執行或偵錯 |
| 206 | |
| 207 | #### JetBrains Rider |
| 208 | |
| 209 | 1. 測試方法旁會出現綠色執行圖示 |
| 210 | 2. 點擊執行或偵錯測試 |
| 211 | 3. 使用 Unit Tests 視窗管理測試 |
| 212 | |
| 213 | ## 專案參考設定原則 |
| 214 | |
| 215 | ### 參考方向規則 |
| 216 | |
| 217 | ```text |
| 218 | 測試專案 → 主專案 (正確) |
| 219 | 主專案 → 測試專案 (錯誤) |
| 220 | ``` |
| 221 | |
| 222 | **測試專案應該參考主專案,但主專案絕對不應參考測試專案。** |
| 223 | |
| 224 | ### 設定專案參考 |
| 225 | |
| 226 | ```powershell |
| 227 | # 讓測試專案參考主專案 |
| 228 | dotnet add tests/MyProject.Core.Tests/MyProject.Core.Tests.csproj reference src/MyProject.Core/MyProject.Core.csproj |
| 229 | ``` |
| 230 | |
| 231 | 在 csproj 中會產生: |
| 232 | |
| 233 | ```xml |
| 234 | <ItemGroup> |
| 235 | <ProjectReference Include="..\..\src\MyProject.Core\MyProject.Core.csproj" /> |
| 236 | </ItemGroup> |
| 237 | ``` |
| 238 | |
| 239 | ## 進階:多個測試專案的組織 |
| 240 | |
| 241 | 當專案變大時,可能需要多個測試專案: |
| 242 | |
| 243 | ```text |
| 244 | MyProject/ |
| 245 | ├── src/ |
| 246 | │ ├── MyProject.Core/ |
| 247 | │ ├── MyProject.Web/ |
| 248 | │ └── MyProjec |