Code coverage collection is currently disabled for the net481 target because coverlet 8.0.0 crashes when instrumenting .NET Framework assemblies. This issue tracks re-enabling it once the upstream bugs are fixed.
Issue
Debug/x64 PR builds fail at test execution (not compilation), with every test in the net481 leg throwing:
System.TypeInitializationException : The type initializer for
'Coverlet.Core.Instrumentation.Tracker.Microsoft.Private.Windows.Polyfills.Tests_d6550c7c-fd38-4022-a909-2613cf55c4ed'
threw an exception.
---- System.IO.FileNotFoundException : Could not load file or assembly
'System.Runtime, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'
or one of its dependencies. The system cannot find the file specified.
Only this leg is affected because eng/pipelines/build-PR.yml enables Coverage solely for public Debug x64 builds.
Root cause
Commit f3422f9 (#14371) bumped CoverletMSBuildPackageVersion from 6.0.0 to 8.0.0 in eng/Versions.props.
Coverlet 8.0.0 selects its task assembly by MSBuild host, not target framework (buildMultiTargeting/coverlet.msbuild.props):
<CoverletToolsPath Condition="'$(CoverletToolsPath)' == '' and '$(MSBuildRuntimeType)' == 'Core'">$(MSBuildThisFileDirectory)..\tasks\net8.0\</CoverletToolsPath>
Arcade builds with dotnet build, so the net8.0 flavor is loaded. Its coverlet.core.dll references System.Runtime 8.0.0.0 (the netstandard2.0 flavor, and 6.0.0, reference netstandard 2.0.0.0). The instrumenter copies its tracker template IL out of the loaded coverlet.core.dll into the assembly under test, carrying that reference along — so the tracker injected into our net481 test assembly references an assembly the .NET Framework CLR cannot resolve, and its static constructor throws on the first recorded hit.
This is an acknowledged upstream regression, not an intentional change: coverlet-coverage/coverlet#1818 (identical repro on net481/x64, labeled bug, fixed in coverlet 8.0.1).
Temporary fix
In Directory.Build.props, inside the '$(Coverage)' == 'true' group:
<CollectCoverage Condition="'$(TargetFramework)' == 'net481'">false</CollectCoverage>
Tests still build and run; only .NET Framework coverage collection is skipped. There is no real loss of signal — that leg was producing a red build and no valid coverage data.
Affected projects (the only ones that are both IsTestProject=true and target net481):
| Project |
Effect |
Microsoft.Private.Windows.Polyfills.Tests |
No longer contributes coverage (its $(NetCurrent) leg already had CollectCoverage=false) |
System.Private.Windows.Core.Tests |
net481 leg not instrumented; .NET leg unchanged |
Change needed once coverlet fixes this
Do not simply bump the package version — every release after 6.x is still broken for .NET Framework. All references below are in the coverlet-coverage/coverlet repo:
Wait for coverlet-coverage/coverlet#1985 and coverlet-coverage/coverlet#2010 to ship in a release, then:
- Update
CoverletMSBuildPackageVersion in eng/Versions.props.
- Remove the
CollectCoverage override and its explanatory comment from Directory.Build.props.
- Verify a
net481 coverage file is actually produced under artifacts\bin\<project>\Debug\net481\coverage\ — the failure mode in coverlet-coverage/coverlet#1842 is silent, so a green build alone does not confirm success.
Code coverage collection is currently disabled for the
net481target because coverlet 8.0.0 crashes when instrumenting .NET Framework assemblies. This issue tracks re-enabling it once the upstream bugs are fixed.Issue
Debug/x64 PR builds fail at test execution (not compilation), with every test in the
net481leg throwing:Only this leg is affected because
eng/pipelines/build-PR.ymlenablesCoveragesolely for public Debug x64 builds.Root cause
Commit f3422f9 (#14371) bumped
CoverletMSBuildPackageVersionfrom 6.0.0 to 8.0.0 ineng/Versions.props.Coverlet 8.0.0 selects its task assembly by MSBuild host, not target framework (
buildMultiTargeting/coverlet.msbuild.props):Arcade builds with
dotnet build, so thenet8.0flavor is loaded. Itscoverlet.core.dllreferencesSystem.Runtime 8.0.0.0(thenetstandard2.0flavor, and 6.0.0, referencenetstandard 2.0.0.0). The instrumenter copies its tracker template IL out of the loadedcoverlet.core.dllinto the assembly under test, carrying that reference along — so the tracker injected into our net481 test assembly references an assembly the .NET Framework CLR cannot resolve, and its static constructor throws on the first recorded hit.This is an acknowledged upstream regression, not an intentional change: coverlet-coverage/coverlet#1818 (identical repro on
net481/x64, labeledbug, fixed in coverlet 8.0.1).Temporary fix
In
Directory.Build.props, inside the'$(Coverage)' == 'true'group:Tests still build and run; only .NET Framework coverage collection is skipped. There is no real loss of signal — that leg was producing a red build and no valid coverage data.
Affected projects (the only ones that are both
IsTestProject=trueand targetnet481):Microsoft.Private.Windows.Polyfills.Tests$(NetCurrent)leg already hadCollectCoverage=false)System.Private.Windows.Core.Testsnet481leg not instrumented; .NET leg unchangedChange needed once coverlet fixes this
Do not simply bump the package version — every release after 6.x is still broken for .NET Framework. All references below are in the coverlet-coverage/coverlet repo:
netstandard 2.0.0.0)TypeInitializationException: Could not load type 'System.Collections.Concurrent.ConcurrentBag\1'onnet481` (coverlet-coverage/coverlet#2009); fix (coverlet-coverage/coverlet#2010) unreleasedWait for coverlet-coverage/coverlet#1985 and coverlet-coverage/coverlet#2010 to ship in a release, then:
CoverletMSBuildPackageVersionineng/Versions.props.CollectCoverageoverride and its explanatory comment fromDirectory.Build.props.net481coverage file is actually produced underartifacts\bin\<project>\Debug\net481\coverage\— the failure mode in coverlet-coverage/coverlet#1842 is silent, so a green build alone does not confirm success.