coverlet-coverage / coverlet

Cross platform code coverage for .NET
MIT License
2.93k stars 386 forks source link

Uncovered lines in .NET 8 #1555

Closed samuel-utbult-oborgen closed 6 months ago

samuel-utbult-oborgen commented 7 months ago

Describe the bug When creating a record inheriting another record in a .NET 8 project, the initial line containing public record is reported as not covered by tests even though the record is used in the tests.

To Reproduce

  1. Create a record.
  2. Create another record inheriting that record.
  3. Create a test using the second record.
  4. Run the test with test coverage.
  5. The line containing public record on the second record is reported as not tested.

Here is an example project showcasing the problem: https://github.com/samuel-utbult-oborgen/coverlet-missing-line-example

Expected behavior The uncovered line should either be covered or ignored.

Actual behavior The line is reported as uncovered.

Configuration The following environment it used:

gburkecw commented 7 months ago

we are are having this issue since the MSBUILD 17.8 update, but for .NET 7 projects. GH Actions updated their latest agents to use MSBUILD 17.8 and we started seeing this issue.

For now as a workaround we are building with older agents that still have MSBuild 17.7, but I'm also going to see if I can specify an older language version in the csproj or something.

Still, it seems like this might prevent us from updating to .NET 8

samuel-utbult-oborgen commented 7 months ago

I'm also going to see if I can specify an older language version in the csproj or something.

I can confirm that this does not work at least when it comes to updating to .NET 8. My computer has .NET 8 installed but all .csproj files in the project I'm working on have <TargetFramework>net7.0</TargetFramework> specified and the coverage problem is still present.

Bertk commented 7 months ago

Hi, thank you for the information but I can not reproduce the error using the latest preview.

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>net8.0</TargetFramework>
    <LangVersion>12.0</LangVersion>
    <ImplicitUsings>disable</ImplicitUsings>
    <Nullable>enable</Nullable>

    <IsPackable>false</IsPackable>
    <IsTestProject>true</IsTestProject>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
    <PackageReference Include="xunit" Version="2.6.2" />
    <PackageReference Include="xunit.runner.visualstudio" Version="2.5.4">
      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
      <PrivateAssets>all</PrivateAssets>
    </PackageReference>
    <PackageReference Include="coverlet.collector" Version="6.0.1-preview.25.g21d3964f03">
      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
      <PrivateAssets>all</PrivateAssets>
    </PackageReference>
  </ItemGroup>

  <ItemGroup>
    <ProjectReference Include="..\ExampleProject\ExampleProject.csproj" />
  </ItemGroup>

</Project>
image
C:\GitHub\coverlet-missing-line-example>dotnet --info
.NET SDK:
 Version:           8.0.100
 Commit:            57efcf1350
 Workload version:  8.0.100-manifests.71b9f198

Runtime Environment:
 OS Name:     Windows
 OS Version:  10.0.22631
 OS Platform: Windows
 RID:         win-x64
 Base Path:   C:\Program Files\dotnet\sdk\8.0.100\

.NET workloads installed:
 Workload version: 8.0.100-manifests.71b9f198
There are no installed workloads to display.

Host:
  Version:      8.0.0
  Architecture: x64
  Commit:       5535e31a71

.NET SDKs installed:
  6.0.417 [C:\Program Files\dotnet\sdk]
  7.0.404 [C:\Program Files\dotnet\sdk]
  8.0.100 [C:\Program Files\dotnet\sdk]

.NET runtimes installed:
  Microsoft.AspNetCore.App 6.0.25 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 7.0.14 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 8.0.0 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.NETCore.App 6.0.15 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 6.0.25 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 7.0.14 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 8.0.0 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.WindowsDesktop.App 6.0.15 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 6.0.25 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 7.0.14 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 8.0.0 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]

Other architectures found:
  x86   [C:\Program Files (x86)\dotnet]
    registered at [HKLM\SOFTWARE\dotnet\Setup\InstalledVersions\x86\InstallLocation]

Environment variables:
  Not set

global.json file:
  Not found

Learn more:
  https://aka.ms/dotnet/info

Download .NET:
  https://aka.ms/dotnet/download

C:\GitHub\coverlet-missing-line-example>dotnet msbuild --version
MSBuild version 17.8.3+195e7f5a3 for .NET
17.8.3.51904

Per the published support rules, the minimum Visual Studio and MSBuild version for each new major release is updated with a one quarter delay. For the .NET 8 release, 8.0.100 requires version 17.7 to be loaded but only supports targeting .NET 7 in that version. To target net8.0, you must use version 17.8 or later.

samuel-utbult-oborgen commented 7 months ago

I have updated the example. Could you try the following?

  1. Install the tool dotnet-reportgenerator-globaltool.
  2. Run the test with test coverage as before.
  3. Copy the path to the generated .info file.
  4. Run this command: dotnet tool run reportgenerator -reports:[paste the path here] -targetdir:coverage/html
  5. Open coverage/html/index.html in a web browser.
  6. Click on InheritedRecord.
  7. Line 3 is reported as uncovered, just as the .info file described.
Bertk commented 7 months ago

Thanks I will check it tomorrow.

By the way, please use this command to generate a valid .gitignore file for the example git repository: dotnet new gitignore -force

Bertk commented 7 months ago

The coverlet.runsetting excludes generated code and therefore uncovered line is removed.

dotnet test --collect:"XPlat Code Coverage;Format=lcov" --settings coverlet.runsettings

<?xml version="1.0" encoding="utf-8"?>
<RunSettings>
  <DataCollectionRunSettings>
    <DataCollectors>
      <DataCollector friendlyName="XPlat code coverage">
        <Configuration>
          <ExcludeByAttribute>Obsolete,GeneratedCodeAttribute,CompilerGeneratedAttribute</ExcludeByAttribute>
        </Configuration>
      </DataCollector>
    </DataCollectors>
  </DataCollectionRunSettings>
</RunSettings>
Screenshot 2023-12-04 153837 image

Please check whether this is an acceptable solution. This will also remove async methods from the coverage results (more details #1561).

samuel-utbult-oborgen commented 7 months ago

I can confirm the proposed solution removes the uncovered line in InheritedRecord. However, the tradeoff of not covering asynchronous methods is not acceptable in my situation as the project I am aiming to upgrade to .NET 8 consists in a large part of asynchronous methods. The branch exclude_generated_code in my example project showcases this problem.

camp-007 commented 5 months ago

@daveMueller Awesome! Thank you for your work on this. Can you explain the release cadence or when this change will be available on nuget?

pinkfloydx33 commented 5 months ago

@daveMueller Any idea when this will make it into the nightly build? The last nightly was two days prior to merging this in.... it'd be nice to have these fixes there as well

daveMueller commented 5 months ago

@pinkfloydx33 we are working on fixing the nightly pipeline. @camp-007 a new release currently has a really high priority among the maintainers but we had some issues with that in the last months. I'm optimistic that we can publish a new release in the near future. Until then you can consume the nightly build.

samuel-utbult-oborgen commented 5 months ago

I can confirm the solution implemented in nightly works in my example project: https://github.com/samuel-utbult-oborgen/coverlet-missing-line-example/tree/fix

joe-camp-nelnet commented 4 months ago

@daveMueller Any news or updates on when this will make it to a formal release on nuget?