coverlet-coverage / coverlet

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

[BUG] Records show no coverage #1633

Open tisonv opened 4 months ago

tisonv commented 4 months ago

Describe the bug With .Net 8, records show no coverage Tested with the nightly build too I read #1561 #1607 #1576

To Reproduce

public sealed record FolderInfoDto
{
    public bool IsHidden { get; init; }
    public long Creation { get; init; }
}
return new FolderInfoDto
{
    Creation = f.Creation,
    IsHidden = !string.IsNullOrEmpty(f.Mode) && 'h' == f.Mode[3]
};
internal abstract record BasicFolderDto
{
    public string? DfsMappedPath { get; init; }
    public string Path { get; init; } = null!;
}

internal sealed record CreateFolderDto : BasicFolderDto;

CreateFolderDto dto = new()
{
    Path = args != null && args.TryGetValue("path", out var path) ? (string)path : @"F:\rep1\rep2",
};
internal sealed record DeleteFolderDto : BasicFolderDto
{
    public bool Recurse { get; init; }
    public bool Force { get; init; }
}

DeleteFolderDto dto = new()
{
    Path = @"L:\path\",
};

Expected behavior FolderInfoDto, CreateFolderDto, DeleteFolderDto, BasicFolderDto are marked as covered.

Actual behavior They are marked as not covered.

Configuration (please complete the following information): Please provide more information on your .NET configuration:

Additional context

test.runsettings:

<?xml version="1.0" encoding="utf-8"?>
<RunSettings>
    <RunConfiguration>
        <ResultsDirectory>.\TestResults</ResultsDirectory>
        <TargetPlatform>x64</TargetPlatform>
        <TargetFramework>net8.0</TargetFramework>
    </RunConfiguration>

    <DataCollectionRunSettings>
        <DataCollectors>
            <DataCollector friendlyName="XPlat code coverage">
                <Configuration>
                    <Format>cobertura</Format>
                    <Exclude>[coverlet.*.tests?]*,[*]Coverlet.Core*,[*]xunit*</Exclude>
                </Configuration>
            </DataCollector>
        </DataCollectors>
    </DataCollectionRunSettings>
</RunSettings>

:exclamation: Please also read Known Issues

daveMueller commented 4 months ago

Thanks for reporting and providing a repro. I see if I can get the discussion in #1576 started. I think we then would have less issues with records.

tisonv commented 4 months ago

Our SonarQube would not allow my PR since coverage was subpar. I was just refactoring dtos . I had to [ExcludeFromCodeCoverage] for the time being

daveMueller commented 3 months ago

Could you elaborate a bit on how to reproduce this? With my setup I can get coverage for those records.

grafik

tisonv commented 2 months ago

Hello !

Latest SonarQube expects all the lines to be covered https://community.sonarsource.com/t/sonarqube-not-showing-coverage-for-inherited-record/107476 I'm not sure whether they should be marked as covered or not

image

Steve-OH commented 4 days ago

A hopefully useful additional data point

I have an internal record:

internal record Foo
{
    public string Bar() => "baz";
}

And an associated test project with a test:

[TestFixture]
internal class FooTests
{
    [Test]
    public void FooBarShouldReturnBaz()
    {
        var foo = new Foo();
        Assert.That(foo.Bar(), Is.EqualTo("baz"));
    }
}

After running the test, the method call shows that it was covered, but the record itself does not:

image

If I modify the record declaration to include the redundant primary constructor parentheses:

internal record Foo()
{
    public string Bar() => "baz";
}

and repeat the test, this time I get green all around:

image