Skip to content

Branch coverage Issue - async delegate + await using #1284

@g0dm0d3

Description

@g0dm0d3

Hi guys!
Found one more interesting case.

Code:

namespace CoverletAsyncAwait;

public class SomeClass
{
    public async Task SomeMethod()
    {
        await SomeInternalMethod(async () =>
        {
            await using var stream = new MemoryStream();
            await Task.CompletedTask;
        });
    }

    private static async Task SomeInternalMethod(Func<Task> work)
    {
        await work();
    }
}

Test:

using System.Threading.Tasks;
using NUnit.Framework;

namespace CoverletAsyncAwait.Tests;

[TestFixture]
public class TestSomeClass
{
    [Test]
    public async Task SomeTest()
    {
        var someClass = new SomeClass();
        await someClass.SomeMethod();
    }
}

Expected:
Full branch coverage

Actual:
Partially covered (1 visits, 4 of 6 branches are covered)

Output:
image

Report:

<?xml version="1.0" encoding="utf-8"?>
<coverage line-rate="1" branch-rate="0.6666" version="1.9" timestamp="1643610246" lines-covered="10" lines-valid="10" branches-covered="4" branches-valid="6">
  <sources>
    <source>F:\</source>
  </sources>
  <packages>
    <package name="CoverletAsyncAwait" line-rate="1" branch-rate="0.6666" complexity="8">
      <classes>
        <class name="CoverletAsyncAwait.SomeClass/&lt;&gt;c/&lt;&lt;SomeMethod&gt;b__0_0&gt;d" filename="Work\experiments\CoverletAsyncAwait\CoverletAsyncAwait\SomeClass.cs" line-rate="1" branch-rate="0.6666" complexity="6">
          <methods>
            <method name="MoveNext" signature="()" line-rate="1" branch-rate="0.6666" complexity="6">
              <lines>
                <line number="8" hits="1" branch="False" />
                <line number="9" hits="1" branch="False" />
                <line number="10" hits="1" branch="True" condition-coverage="66.66% (4/6)">
                  <conditions>
                    <condition number="181" type="jump" coverage="100%" />
                    <condition number="299" type="jump" coverage="50%" />
                    <condition number="339" type="jump" coverage="50%" />
                  </conditions>
                </line>
                <line number="11" hits="2" branch="False" />
              </lines>
            </method>
          </methods>
          <lines>
            <line number="8" hits="1" branch="False" />
            <line number="9" hits="1" branch="False" />
            <line number="10" hits="1" branch="True" condition-coverage="66.66% (4/6)">
              <conditions>
                <condition number="181" type="jump" coverage="100%" />
                <condition number="299" type="jump" coverage="50%" />
                <condition number="339" type="jump" coverage="50%" />
              </conditions>
            </line>
            <line number="11" hits="2" branch="False" />
          </lines>
        </class>
        <class name="CoverletAsyncAwait.SomeClass/&lt;SomeInternalMethod&gt;d__1" filename="Work\experiments\CoverletAsyncAwait\CoverletAsyncAwait\SomeClass.cs" line-rate="1" branch-rate="1" complexity="1">
          <methods>
            <method name="MoveNext" signature="()" line-rate="1" branch-rate="1" complexity="1">
              <lines>
                <line number="15" hits="1" branch="False" />
                <line number="16" hits="1" branch="False" />
                <line number="17" hits="1" branch="False" />
              </lines>
            </method>
          </methods>
          <lines>
            <line number="15" hits="1" branch="False" />
            <line number="16" hits="1" branch="False" />
            <line number="17" hits="1" branch="False" />
          </lines>
        </class>
        <class name="CoverletAsyncAwait.SomeClass/&lt;SomeMethod&gt;d__0" filename="Work\experiments\CoverletAsyncAwait\CoverletAsyncAwait\SomeClass.cs" line-rate="1" branch-rate="1" complexity="1">
          <methods>
            <method name="MoveNext" signature="()" line-rate="1" branch-rate="1" complexity="1">
              <lines>
                <line number="6" hits="1" branch="False" />
                <line number="7" hits="1" branch="False" />
                <line number="12" hits="1" branch="False" />
              </lines>
            </method>
          </methods>
          <lines>
            <line number="6" hits="1" branch="False" />
            <line number="7" hits="1" branch="False" />
            <line number="12" hits="1" branch="False" />
          </lines>
        </class>
      </classes>
    </package>
  </packages>
</coverage>

Reproduced in .NET 6, Coverlet 3.1.1

Metadata

Metadata

Assignees

No one assigned

    Labels

    staletenet-coverageIssue related to possible incorrect coverageuntriagedTo be investigated

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions