coverlet.collector未将.NET MAUI项目纳入coverage.cobertura.xml的问题
.NET MAUI项目代码覆盖率未被coverlet.collector收集的问题排查与解决
问题描述
我有一个.NET MAUI项目和单元测试项目处于同一解决方案中,测试项目已引用MAUI项目且所有测试运行正常。但使用coverlet.collector生成的coverage.cobertura.xml文件仅包含普通.NET 6项目Service,完全未收录MAUI项目的代码覆盖率。本地Windows 10环境与ADO管道中均出现此问题,执行的测试命令为:
dotnet test --collect:"XPlat Code Coverage"
测试项目proj文件
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <TargetFramework>net6.0</TargetFramework> <IsPackable>false</IsPackable> <EnableNETAnalyzers>true</EnableNETAnalyzers> <Nullable>enable</Nullable> </PropertyGroup> <ItemGroup> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.4.0" /> <PackageReference Include="xunit" Version="2.4.2" /> <PackageReference Include="xunit.runner.visualstudio" Version="2.4.5"> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <PrivateAssets>all</PrivateAssets> </PackageReference> <PackageReference Include="coverlet.collector" Version="3.2.0"> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <PrivateAssets>all</PrivateAssets> </PackageReference> <PackageReference Include="FluentAssertions" Version="6.8.0" /> <PackageReference Include="NSubstitute" Version="4.4.0" /> </ItemGroup> <ItemGroup> <ProjectReference Include="..\..\Source\MauiApp.Client\MauiApp.Client.csproj" /> <ProjectReference Include="..\..\Source\Service\Service.csproj" /> </ItemGroup> <ItemGroup> <Folder Include="Service\" /> </ItemGroup> </Project>
.NET MAUI项目proj文件
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <!--<TargetFrameworks>net6.0-ios;net6.0</TargetFrameworks>--> <TargetFrameworks>net6.0</TargetFrameworks> <TargetFrameworks Condition="$([MSBuild]::IsOSPlatform('windows'))">net6.0-windows10.0.19041.0;$(TargetFrameworks)</TargetFrameworks> <!-- Uncomment to also build the tizen app. You will need to install tizen by following this: https://github.com/Samsung/Tizen.NET --> <!-- <TargetFrameworks>$(TargetFrameworks);net6.0-tizen</TargetFrameworks> --> <OutputType Condition="'$(TargetFramework)' != 'net6.0'">Exe</OutputType> <RootNamespace>$(MSBuildProjectName.Replace("-", "_"))</RootNamespace> <UseMaui>true</UseMaui> <SingleProject>true</SingleProject> <ImplicitUsings>enable</ImplicitUsings> <Nullable>enable</Nullable> <!-- Display name --> <ApplicationTitle>GridSwift</ApplicationTitle> <!-- App Identifier --> <ApplicationId>someapp.gist</ApplicationId> <ApplicationIdGuid>CCB22D0C-6528-4C55-9BB7-2CAB312363AB</ApplicationIdGuid> <!-- Versions --> <ApplicationDisplayVersion>1.0</ApplicationDisplayVersion> <ApplicationVersion>1</ApplicationVersion> <!-- <SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'">15.4</SupportedOSPlatformVersion>--> <SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'">10.0.19041.0</SupportedOSPlatformVersion> <TargetPlatformMinVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'">10.0.19041.0</TargetPlatformMinVersion> <DefaultLanguage>en-us</DefaultLanguage> </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Debug|net6.0-windows10.0.19041.0|AnyCPU'"> <TreatWarningsAsErrors>True</TreatWarningsAsErrors> </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Release|net6.0-windows10.0.19041.0|AnyCPU'"> <TreatWarningsAsErrors>True</TreatWarningsAsErrors> </PropertyGroup> <ItemGroup> <!-- App Icon --> <MauiIcon Include="Resources\AppIcon\appicon.svg" ForegroundFile="Resources\AppIcon\appiconfg.svg" Color="#512BD4" /> <!-- Splash Screen --> <MauiSplashScreen Include="Resources\Splash\splash.svg" Color="#512BD4" BaseSize="128,128" /> <!-- Images --> <MauiImage Include="Resources\Images\*" /> <MauiImage Update="Resources\Images\dotnet_bot.svg" BaseSize="168,208" /> <!-- Custom Fonts --> <MauiFont Include="Resources\Fonts\*" /> <!-- Raw Assets (also remove the "Resources\Raw" prefix) --> <MauiAsset Include="Resources\Raw\**" LogicalName="%(RecursiveDir)%(Filename)%(Extension)" /> </ItemGroup> <ItemGroup> <PackageReference Include="Microsoft.Identity.Client" Version="4.48.0" /> <PackageReference Include="Newtonsoft.Json" Version="13.0.2" /> <PackageReference Include="ReduxSimple" Version="3.7.0" /> </ItemGroup> <ItemGroup> <MauiXaml Update="Views\LoginView.xaml"> <Generator>MSBuild:Compile</Generator> </MauiXaml> </ItemGroup> </Project>
原因分析
- 目标框架不匹配:MAUI项目默认编译多框架(即使注释了iOS目标,仍包含net6.0和Windows目标),而测试项目仅以net6.0为目标框架,coverlet无法正确关联MAUI项目的编译输出。
- 输出类型限制:MAUI项目针对非net6.0框架时,OutputType设为Exe,coverlet默认跳过可执行项目的覆盖率收集,仅处理类库类型项目。
- 版本兼容性:使用的coverlet.collector 3.2.0版本对.NET MAUI的支持不完善,早期版本对MAUI这类特殊项目的识别存在缺陷。
解决方案
1. 统一目标框架
修改MAUI项目的TargetFrameworks,强制仅编译net6.0框架,避免多框架导致的匹配问题:
<PropertyGroup> <!-- 替换原有多框架配置,仅保留net6.0 --> <TargetFrameworks>net6.0</TargetFrameworks> <!-- 移除Windows目标的条件编译行 --> </PropertyGroup>
2. 强制coverlet收集可执行项目
在测试项目的proj文件中添加coverlet配置,明确指定要收集MAUI项目的覆盖率,并允许收集可执行项目:
<PropertyGroup> <!-- 保留原有属性,新增以下配置 --> <CollectCoverage>true</CollectCoverage> <IncludeTestAssembly>false</IncludeTestAssembly> <!-- 指定MAUI项目的程序集名称前缀 --> <Include>[MauiApp.Client]*</Include> <!-- 允许收集可执行类型项目的覆盖率 --> <IncludeExe>true</IncludeExe> </PropertyGroup>
3. 升级coverlet.collector版本
将coverlet.collector升级到最新稳定版本(如6.0.0),新版本对.NET MAUI的支持更完善:
<PackageReference Include="coverlet.collector" Version="6.0.0"> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <PrivateAssets>all</PrivateAssets> </PackageReference>
4. 改用coverlet.msbuild替代collector
如果collector方式仍有问题,可切换为coverlet.msbuild包,通过MSBuild参数直接控制:
首先在测试项目中添加包引用:
<PackageReference Include="coverlet.msbuild" Version="6.0.0"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> </PackageReference>
然后执行测试命令:
dotnet test /p:CollectCoverage=true /p:CoverletOutputFormat=cobertura /p:Include="[MauiApp.Client]*" /p:IncludeExe=true
内容的提问来源于stack exchange,提问作者dik1977
相关产品推荐
相关产品推荐

