$npx -y skills add wshaddix/dotnet-skills --skill dotnet-add-testingAdding test infrastructure to a .NET project. Scaffolds xUnit project, coverlet, layout.
| 1 | # dotnet-add-testing |
| 2 | |
| 3 | Add test infrastructure scaffolding to an existing .NET project. Creates test projects with xUnit, configures code coverage with coverlet, and sets up the conventional directory structure. |
| 4 | |
| 5 | **Scope boundary:** This skill provides **test project scaffolding** only. For in-depth testing patterns -- xUnit v3 features, integration testing with WebApplicationFactory, UI testing, snapshot testing, test quality metrics, and testing strategy guidance -- see [skill:dotnet-testing-strategy] and the related testing skills. |
| 6 | |
| 7 | **Prerequisites:** Run [skill:dotnet-version-detection] first to determine SDK version and TFM. Run [skill:dotnet-project-analysis] to understand existing solution structure. |
| 8 | |
| 9 | Cross-references: [skill:dotnet-project-structure] for overall solution layout conventions, [skill:dotnet-scaffold-project] which includes test scaffolding in new projects, [skill:dotnet-add-analyzers] for test-specific analyzer suppressions. |
| 10 | |
| 11 | --- |
| 12 | |
| 13 | ## Test Project Structure |
| 14 | |
| 15 | Follow the convention of mirroring `src/` project names under `tests/`: |
| 16 | |
| 17 | ``` |
| 18 | MyApp/ |
| 19 | ├── src/ |
| 20 | │ ├── MyApp.Core/ |
| 21 | │ ├── MyApp.Api/ |
| 22 | │ └── MyApp.Infrastructure/ |
| 23 | └── tests/ |
| 24 | ├── MyApp.Core.UnitTests/ |
| 25 | ├── MyApp.Api.UnitTests/ |
| 26 | ├── MyApp.Api.IntegrationTests/ |
| 27 | └── Directory.Build.props # Test-specific build settings |
| 28 | ``` |
| 29 | |
| 30 | Naming conventions: |
| 31 | - `*.UnitTests` -- isolated tests with no external dependencies |
| 32 | - `*.IntegrationTests` -- tests that use real infrastructure (database, HTTP, file system) |
| 33 | - `*.FunctionalTests` -- end-to-end tests through the full application stack |
| 34 | |
| 35 | --- |
| 36 | |
| 37 | ## Step 1: Create the Test Project |
| 38 | |
| 39 | ```bash |
| 40 | # Create xUnit test project |
| 41 | dotnet new xunit -n MyApp.Core.UnitTests -o tests/MyApp.Core.UnitTests |
| 42 | |
| 43 | # Add to solution |
| 44 | dotnet sln add tests/MyApp.Core.UnitTests/MyApp.Core.UnitTests.csproj |
| 45 | |
| 46 | # Add reference to the project under test |
| 47 | dotnet add tests/MyApp.Core.UnitTests/MyApp.Core.UnitTests.csproj \ |
| 48 | reference src/MyApp.Core/MyApp.Core.csproj |
| 49 | ``` |
| 50 | |
| 51 | ### Clean Up Generated Project |
| 52 | |
| 53 | Remove properties already defined in `Directory.Build.props`: |
| 54 | |
| 55 | ```xml |
| 56 | <!-- tests/MyApp.Core.UnitTests/MyApp.Core.UnitTests.csproj --> |
| 57 | <Project Sdk="Microsoft.NET.Sdk"> |
| 58 | <ItemGroup> |
| 59 | <PackageReference Include="Microsoft.NET.Test.Sdk" /> |
| 60 | <PackageReference Include="xunit.v3" /> |
| 61 | <PackageReference Include="xunit.runner.visualstudio" /> |
| 62 | <PackageReference Include="coverlet.collector" /> |
| 63 | </ItemGroup> |
| 64 | <ItemGroup> |
| 65 | <ProjectReference Include="..\..\src\MyApp.Core\MyApp.Core.csproj" /> |
| 66 | </ItemGroup> |
| 67 | </Project> |
| 68 | ``` |
| 69 | |
| 70 | With CPM, `Version` attributes are managed in `Directory.Packages.props`. Remove them from the generated `.csproj`. |
| 71 | |
| 72 | --- |
| 73 | |
| 74 | ## Step 2: Add Test-Specific Build Properties |
| 75 | |
| 76 | Create `tests/Directory.Build.props` to customize settings for all test projects: |
| 77 | |
| 78 | ```xml |
| 79 | <!-- tests/Directory.Build.props --> |
| 80 | <Project> |
| 81 | <Import Project="$([MSBuild]::GetPathOfFileAbove('Directory.Build.props', '$(MSBuildThisFileDirectory)../'))" /> |
| 82 | <PropertyGroup> |
| 83 | <IsPackable>false</IsPackable> |
| 84 | <IsTestProject>true</IsTestProject> |
| 85 | <!-- Use Microsoft.Testing.Platform v2 runner (requires Microsoft.NET.Test.Sdk 17.13+/18.x) --> |
| 86 | <UseMicrosoftTestingPlatformRunner>true</UseMicrosoftTestingPlatformRunner> |
| 87 | <!-- Relax strictness for test projects --> |
| 88 | <TreatWarningsAsErrors>false</TreatWarningsAsErrors> |
| 89 | </PropertyGroup> |
| 90 | </Project> |
| 91 | ``` |
| 92 | |
| 93 | This imports the root `Directory.Build.props` (for shared settings like `Nullable`, `ImplicitUsings`, `LangVersion`) and overrides test-specific properties. |
| 94 | |
| 95 | --- |
| 96 | |
| 97 | ## Step 3: Register Test Packages in CPM |
| 98 | |
| 99 | Add test package versions to `Directory.Packages.props`: |
| 100 | |
| 101 | ```xml |
| 102 | <!-- In Directory.Packages.props --> |
| 103 | <ItemGroup> |
| 104 | <!-- Test packages --> |
| 105 | <PackageVersion Include="Microsoft.NET.Test.Sdk" Version="18.0.1" /> |
| 106 | <PackageVersion Include="xunit.v3" Version="3.2.2" /> |
| 107 | <PackageVersion Include="xunit.runner.visualstudio" Version="3.1.5" /> |
| 108 | <PackageVersion Include="coverlet.collector" Version="8.0.0" /> |
| 109 | </ItemGroup> |
| 110 | ``` |
| 111 | |
| 112 | ### Optional: Mocking Library |
| 113 | |
| 114 | Add a mocking library if the project needs test doubles: |
| 115 | |
| 116 | ```xml |
| 117 | <PackageVersion Include="NSubstitute" Version="5.3.0" /> |
| 118 | ``` |
| 119 | |
| 120 | Or for assertion libraries: |
| 121 | |
| 122 | ```xml |
| 123 | <PackageVersion Include="FluentAssertions" Version="8.0.1" /> |
| 124 | ``` |
| 125 | |
| 126 | --- |
| 127 | |
| 128 | ## Step 4: Configure Code Coverage |
| 129 | |
| 130 | ### Coverlet (Collector Mode) |
| 131 | |
| 132 | The `coverlet.collector` package integrates with `dotnet test` via the data collector. No additional configuration is needed for basic coverage. |
| 133 | |
| 134 | Generate coverage reports: |
| 135 | |
| 136 | ```bash |
| 137 | # Collect coverage (Cobertura format by default) |
| 138 | dotnet test --collect:"XPlat Code Coverage" |
| 139 | |
| 140 | # Results appear in TestResults/*/coverage.cobertura.xml |
| 141 | ``` |
| 142 | |
| 143 | ### Coverage Thresholds |
| 144 | |
| 145 | For CI enforcement, use `coverlet.msbuild` for threshold checks: |
| 146 | |
| 147 | ```xml |
| 148 | <!-- In test csproj or tests/Directory.Build.props --> |
| 149 | <PackageReference Includ |