Incorrectly calculate coverage when DisposeAsync is involved

With .Net Core 3 we have a new IAsyncDisposable interface that allows disposing objects asynchronously.

This may be used in two different ways:

await using var someVar = new SomeType();

or

var someVar = new SomeType();
await someVar.DisposeAsync();

It seems, SonarQube calculates conditions coverage incorrectly. Even if all lines are covered with tests, SonarQube marks the line with await using as partially covered with tests (5 of 10 conditions covered) which is nonsense as there are no branches managed by a developer. With the second syntax, the line with DisposeAsync is also marked as partially covered (1 of 2 conditions covered) - that’s better because does not affect overal metrics so badly but still may prevent us from passing quality gates.

The reproduction:

    public class TestClass
    {
        public async Task Example1()
        {
            await using var trans = new MyTransaction();
        }
        
        public async Task Example2()
        {
            var trans = new MyTransaction();
            await trans.DisposeAsync();
        }
    }
    
    public class MyTransaction : IAsyncDisposable
    {
        public async ValueTask DisposeAsync()
        {
        }
    }

    public class UnitTest1
    {
        [Fact]
        public async Task Test1()
        {
            var c = new TestClass();
            await c.Example1().ConfigureAwait(false);
        }

        [Fact]
        public async Task Test2()
        {
            var c = new TestClass();
            await c.Example2().ConfigureAwait(false);
        }
    }

Expected behavior: treat TestClass as having 100% test coverage both by lines and by conditions.

SonarQube Data Center Edition Version 8.3.1 (build 34397)
Testing framework: XUnit 2.4.1
TargetFramework: netcoreapp3.0

Hi @Aleksei-Pankratev,

Welcome to our community forum! What tool/version/command are you using to generate the coverage report? Branch coverage information is taken from this report.

Can you share the coverage report from your small reproducer project?

Oh, I see. We use coverlet.msbuild version 2.8.1 (the same result with 2.9.0 though).

The command line I used is

dotnet test --configuration Release /p:CollectCoverage=true /p:CoverletOutputFormat=opencover /p:CoverletOutput=./TestResults/

It seems, this issue has already been reported there https://github.com/coverlet-coverage/coverlet/issues/914 and it has no direct relation to SonarQube.

Sorry for bothering :blush:

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.