coverlet
coverlet copied to clipboard
[BUG] Code coverage empty on NET8.0 WPF project
Describe the bug Code Coverage on NET8.0 WPF project is empty.
To Reproduce Create a .NET8 WPF project and refrence an enum value out of 'PresentationFramework' as default value.
public class Class
{
public void Method(MessageBoxButton button = MessageBoxButton.OK)
{
}
}
Create a test project with an arbitrary test and run dotnet test --configuration Debug --collect:"XPlat Code Coverage".
Expected behavior Code coverage should not be empty.
Actual behavior The resulting coverage is empty.
When executing:
dotnet test .\TestProject.sln --configuration Debug --collect:"XPlat Code Coverage" --diag:log.txt
The log.datacollector.***.txt contains following exception:
Coverlet.Core.Exceptions.CecilAssemblyResolutionException: AssemblyResolutionException for 'PresentationFramework, Version=8.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35'. Try to add <PreserveCompilationContext>true</PreserveCompilationContext> to test projects </PropertyGroup> or pass '/p:CopyLocalLockFileAssemblies=true' option to the 'dotnet test' command-line
---> Mono.Cecil.AssemblyResolutionException: Failed to resolve assembly: 'PresentationFramework, Version=8.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35'
--- End of inner exception stack trace ---
at Coverlet.Core.Instrumentation.NetstandardAwareAssemblyResolver.TryWithCustomResolverOnDotNetCore(AssemblyNameReference name) in /_/src/coverlet.core/Instrumentation/CecilAssemblyResolver.cs:line 217
at Coverlet.Core.Instrumentation.NetstandardAwareAssemblyResolver.Resolve(AssemblyNameReference name) in /_/src/coverlet.core/Instrumentation/CecilAssemblyResolver.cs:line 129
at Mono.Cecil.MetadataResolver.Resolve(TypeReference type)
at Mono.Cecil.ModuleDefinition.Resolve(TypeReference type)
at Mono.Cecil.TypeReference.Resolve()
at Mono.Cecil.Mixin.CheckedResolve(TypeReference self)
at Mono.Cecil.MetadataBuilder.GetConstantType(TypeReference constant_type, Object constant)
at Mono.Cecil.MetadataBuilder.AddConstant(IConstantProvider owner, TypeReference type)
at Mono.Cecil.MetadataBuilder.AddParameter(UInt16 sequence, ParameterDefinition parameter, ParamTable table)
at Mono.Cecil.MetadataBuilder.AddParameters(MethodDefinition method)
at Mono.Cecil.MetadataBuilder.AddMethod(MethodDefinition method)
at Mono.Cecil.MetadataBuilder.AddMethods(TypeDefinition type)
at Mono.Cecil.MetadataBuilder.AddType(TypeDefinition type)
at Mono.Cecil.MetadataBuilder.AddTypes()
at Mono.Cecil.MetadataBuilder.BuildTypes()
at Mono.Cecil.MetadataBuilder.BuildModule()
at Mono.Cecil.MetadataBuilder.BuildMetadata()
at Mono.Cecil.ModuleWriter.<>c.<BuildMetadata>b__2_0(MetadataBuilder builder, MetadataReader _)
at Mono.Cecil.ModuleDefinition.Read[TItem,TRet](TItem item, Func`3 read)
at Mono.Cecil.ModuleWriter.BuildMetadata(ModuleDefinition module, MetadataBuilder metadata)
at Mono.Cecil.ModuleWriter.Write(ModuleDefinition module, Disposable`1 stream, WriterParameters parameters)
at Mono.Cecil.ModuleWriter.WriteModule(ModuleDefinition module, Disposable`1 stream, WriterParameters parameters)
at Mono.Cecil.ModuleDefinition.Write(Stream stream, WriterParameters parameters)
at Coverlet.Core.Instrumentation.Instrumenter.InstrumentModule() in /_/src/coverlet.core/Instrumentation/Instrumenter.cs:line 325
at Coverlet.Core.Instrumentation.Instrumenter.Instrument() in /_/src/coverlet.core/Instrumentation/Instrumenter.cs:line 148
at Coverlet.Core.Coverage.PrepareModules() in /_/src/coverlet.core/Coverage.cs:line 134
Configuration (please complete the following information):
Please provide more information on your .NET configuration:
* Which coverlet package and version was used? => 6.0.2 also tested 6.0.3-preview.17.g302886a430
* Which version of .NET is the code running on? => net8.0-windows and net9.0-windows
* What OS and version, and what distro if applicable? => Microsoft Windows 10 Enterprise 19045
* What is the architecture (x64, x86, ARM, ARM64)? => x64
* Do you know whether it is specific to that configuration? => no
Additional context
Adding <PreserveCompilationContext>true</PreserveCompilationContext> did not help.
Adding /p:CopyLocalLockFileAssemblies=true did also not help.
:exclamation: Please also read Known Issues
Please provide a repo for analysis. I not able to reproduce the exception.
I have created a repo for this issue. https://github.com/modmynitro/coverlet-test
Thank you for the repo. I updated the target framework and used net48 which solved the problem.
steps:
- dotnet build
- dotnet publish -c debug
- dotnet test --configuration Debug --collect:"XPlat Code Coverage" --diag:log.txt
TestProject\TestProject.csproj
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net48</TargetFramework>
<UseWpf>true</UseWpf>
<LangVersion>10.0</LangVersion>
</PropertyGroup>
</Project>
TestProjectTests\TestProjectTests.csproj
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net48</TargetFramework>
<LangVersion>10.0</LangVersion>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\TestProject\TestProject.csproj"/>
</ItemGroup>
<ItemGroup>
<PackageReference Include="NUnit" Version="4.2.2"/>
<PackageReference Include="NUnit3TestAdapter" Version="4.6.0"/>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.12.0"/>
<PackageReference Include="coverlet.collector" Version="6.0.2">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>
</Project>
coverage.cobertura.xml
<?xml version="1.0" encoding="utf-8"?>
<coverage line-rate="1" branch-rate="1" version="1.9" timestamp="1733822473" lines-covered="2" lines-valid="2" branches-covered="0" branches-valid="0">
<sources>
<source>C:\</source>
</sources>
<packages>
<package name="TestProject" line-rate="1" branch-rate="1" complexity="1">
<classes>
<class name="TestProject.Class" filename="GitHub\coverlet-issue-1713\TestProject\Class.cs" line-rate="1" branch-rate="1" complexity="1">
<methods>
<method name="Method" signature="(System.Windows.MessageBoxButton)" line-rate="1" branch-rate="1" complexity="1">
<lines>
<line number="8" hits="1" branch="False" />
<line number="9" hits="1" branch="False" />
</lines>
</method>
</methods>
<lines>
<line number="8" hits="1" branch="False" />
<line number="9" hits="1" branch="False" />
</lines>
</class>
</classes>
</package>
</packages>
</coverage>
I want to use net8.0 not .NET Framework so this does not help in my situation.
OK. I will investigate (debug) this issue in the next days.
The test project targeting net8.0-windows need the property <SelfContained>true</SelfContained> which resolves the CecilAssemblyResolutionException.
Unfortunately this is not documented anywhere but a hint shall be added for coverlet.msbuild and coverlet.collector.
Solution:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net8.0-windows</TargetFramework>
<LangVersion>10.0</LangVersion>
<PreserveCompilationContext>true</PreserveCompilationContext>
<SelfContained>true</SelfContained>
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\TestProject\TestProject.csproj"/>
</ItemGroup>
<ItemGroup>
<PackageReference Include="NUnit" Version="4.2.2"/>
<PackageReference Include="NUnit3TestAdapter" Version="4.6.0"/>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.12.0"/>
<PackageReference Include="coverlet.collector" Version="6.0.2">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
</ItemGroup>
</Project>
Results:
C:\GitHub\coverlet-issue-1713>dotnet build
Determining projects to restore...
All projects are up-to-date for restore.
TestProject -> C:\GitHub\coverlet-issue-1713\TestProject\bin\Debug\net8.0-windows\TestProject.dll
wpf-template -> C:\GitHub\coverlet-issue-1713\wpf-template\bin\Debug\net8.0-windows\wpf-template.dll
TestProjectTests -> C:\GitHub\coverlet-issue-1713\TestProjectTests\bin\Debug\net8.0-windows\win-x64\TestProjectTests.dll
Build succeeded.
0 Warning(s)
0 Error(s)
Time Elapsed 00:00:04.31
C:\GitHub\coverlet-issue-1713>dotnet test --configuration Debug --collect:"XPlat Code Coverage" --diag:log.txt
Determining projects to restore...
All projects are up-to-date for restore.
TestProject -> C:\GitHub\coverlet-issue-1713\TestProject\bin\Debug\net8.0-windows\TestProject.dll
TestProjectTests -> C:\GitHub\coverlet-issue-1713\TestProjectTests\bin\Debug\net8.0-windows\win-x64\TestProjectTests.dll
Test run for C:\GitHub\coverlet-issue-1713\TestProjectTests\bin\Debug\net8.0-windows\win-x64\TestProjectTests.dll (.NETCoreApp,Version=v8.0)
VSTest version 17.11.1-release-24455-02 (x64)
Starting test execution, please wait...
Logging Vstest Diagnostics in file: C:\GitHub\coverlet-issue-1713\log.txt
A total of 1 test files matched the specified pattern.
Passed! - Failed: 0, Passed: 1, Skipped: 0, Total: 1, Duration: 6 ms - TestProjectTests.dll (net8.0)
Attachments:
C:\GitHub\coverlet-issue-1713\TestProjectTests\TestResults\abf916bc-6eea-4b68-9a2f-7430eea846e1\coverage.cobertura.xml
C:\GitHub\coverlet-issue-1713>type C:\GitHub\coverlet-issue-1713\TestProjectTests\TestResults\abf916bc-6eea-4b68-9a2f-7430eea846e1\coverage.cobertura.xml
<?xml version="1.0" encoding="utf-8"?>
<coverage line-rate="1" branch-rate="1" version="1.9" timestamp="1734340041" lines-covered="2" lines-valid="2" branches-covered="0" branches-valid="0">
<sources>
<source>C:\</source>
</sources>
<packages>
<package name="TestProject" line-rate="1" branch-rate="1" complexity="1">
<classes>
<class name="TestProject.Class" filename="GitHub\coverlet-issue-1713\TestProject\Class.cs" line-rate="1" branch-rate="1" complexity="1">
<methods>
<method name="Method" signature="(System.Windows.MessageBoxButton)" line-rate="1" branch-rate="1" complexity="1">
<lines>
<line number="11" hits="1" branch="False" />
<line number="12" hits="1" branch="False" />
</lines>
</method>
</methods>
<lines>
<line number="11" hits="1" branch="False" />
<line number="12" hits="1" branch="False" />
</lines>
</class>
</classes>
</package>
</packages>
</coverage>
C:\GitHub\coverlet-issue-1713>
I can use this solution as workaround, but we only use dotnet test on our gitlab runners and this solution forces any local build to be self contained.
I would expect the runtime assemblies to be found automatically.
Does this work around work for custom control libraries? My understanding of the <SelfContained/> tag is that it is only for application projects to bundle all the dependencies into a single executable. Which isn't relevant if just writing a custom control library for WPF with tests.
This seems like something that should work, without having to change the project file in anyway. @Bertk The project file you posted in your solution is very different to the one provided by @modmynitro.