C# async methods are not highlighted (red/green) in code coverage

Hello,

I’m using SonarCloud and I have c# source code using Task and async methods.
There is 2 ways I can write the code e.g.:

// version without async
Task DoSomething() {
    return Task.Delay(1000);
}
// version with async
async Task DoSomething(){
    await Task.Delay(1000);
}

When using the version with async/await, the code coverage highlight (red/green) is not shown as it is when using the version without async/await. The coverage reports generated are a bit different but both contains all the information. Also, metadata (Coverage percentage, Uncovered lines count, …) is also the same in either case.

Is there something I missed?

Do both coverage reports show that these lines can be covered by code? SonarQube isn’t involved in producing the coverage reports – only reading them.

I don’t know exactly how to know that but I think yes.

I can say that in the report not using async, the information on coverage is part of an element referencing the class in which the method is defined. E.G.:

<class name="My.Namespace.MyClass" filename="My\Namespace\MyClass.cs" ...  />
    <method name="DoSomething" ...  />

In the report using async, the information on coverage is part of an element referencing a class that seems to be generated. E.G.

<class name="My.Namespace.MyClass/&lt;DoSomething&gt;d__27" filename="My\Namespace\MyClass.cs" ...  />

This might also be relevant.

Thanks for your reply

I saw that blog post you mentioned but I’m not sure it’s the same case.
Now I don’t really know if it’s a problem in the way Visual Studio generates the report or not (because I don’t know what it is supposed to look like).
One thing I know is that the information is in the reports. It’s just not formatted the same way depending on if you use async keyword or not. E.G. the number of Uncovered lines is right in both case. And I can find the number of hits for the lines within those async methods from the report whether I use the async keyword or not. But somehow, it’s not shown with the green/red border in Sonar cloud when I use the async keyword.

I’ll try to do a very simple project and post the full report here. Would that help you help me? :slight_smile:

A reproducer is always helpful. :slight_smile:

I would expect this. If the lines are found as executable (able to covered by tests) and covered… you end up with the same number of uncovered lines as if they aren’t found to be executable.

Well, in my async method, some lines are covered and some other lines are not covered. Yet, all the metadata (lines to cover, uncovered lines, …) is the same between the 2 coverage reports.

I did a small demo project and generated the coverage report. There are 2 methods in the class under test:

public class MyClass
{
    public Task DoSomethingAsync1()
    {
        return Task.Delay(1);
    }
        
    public async Task DoSomethingAsync2()
    {
        await Task.Delay(1);
    }
}

And to me, the report contains all the results:

<?xml version="1.0" encoding="utf-8"?>
<coverage line-rate="1" branch-rate="1" version="1.9" timestamp="1671723050" lines-covered="6" lines-valid="6" branches-covered="0" branches-valid="0">
  <sources>
    <source>D:\</source>
  </sources>
  <packages>
    <package name="MyAsyncLib" line-rate="1" branch-rate="1" complexity="2">
      <classes>
        <class name="MyAsyncLib.MyClass" filename="repos\scratch\MyAsyncLib\MyAsyncLib\MyClass.cs" line-rate="1" branch-rate="1" complexity="1">
          <methods>
            <method name="DoSomethingAsync1" 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="8" hits="1" branch="False" />
              </lines>
            </method>
          </methods>
          <lines>
            <line number="6" hits="1" branch="False" />
            <line number="7" hits="1" branch="False" />
            <line number="8" hits="1" branch="False" />
          </lines>
        </class>
        <class name="MyAsyncLib.MyClass/&lt;DoSomethingAsync2&gt;d__1" filename="repos\scratch\MyAsyncLib\MyAsyncLib\MyClass.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="11" hits="1" branch="False" />
                <line number="12" hits="1" branch="False" />
                <line number="13" hits="1" branch="False" />
              </lines>
            </method>
          </methods>
          <lines>
            <line number="11" hits="1" branch="False" />
            <line number="12" hits="1" branch="False" />
            <line number="13" hits="1" branch="False" />
          </lines>
        </class>
      </classes>
    </package>
  </packages>
</coverage>

The only difference between the DoSomethingAsync2 async method and the other method is that the DoSomethingAsync2 async method is reported in a kind of MyClass<DoSomethingAsync2> generated class.
But the filename and line numbers all match so I presume it’s possible to extract the data from that file and show it correctly in the Sonar cloud UI.

Thanks for the details. I’ve flagged this for some expert attention.

Hi lepagema

can you please show the command and the version of the tool that generated the coverage report? To me, it looks like a limitation of the tool as it doesn’t properly handle the async state machine transposition of the compiler.

Best Martin

Hi @Martin_Strecker
We send a Generic test data (sonarqube.org) xml files, so clearly not an issue on the tool…

And we got the problem, for instance the file contains:

  <file path="MvtMain\Services\Components\Loader\ComponentLoader.cs">
    <lineToCover lineNumber="309" covered="true"/>
    <lineToCover lineNumber="310" covered="true"/>
    <lineToCover lineNumber="312" covered="true"/>
    <lineToCover lineNumber="313" covered="true"/>
    <lineToCover lineNumber="316" covered="true"/>
    <lineToCover lineNumber="318" covered="true"/>
    <lineToCover lineNumber="319" covered="true"/>
    <lineToCover lineNumber="309" covered="true"/>
    <lineToCover lineNumber="310" covered="true"/>
    <lineToCover lineNumber="312" covered="true"/>
    <lineToCover lineNumber="313" covered="true"/>
    <lineToCover lineNumber="316" covered="true"/>
    <lineToCover lineNumber="318" covered="true"/>
    <lineToCover lineNumber="319" covered="true"/>
  </file>

But as you can see in this screen shot these lines are neither red or green, they are not seen as covered, BUT the coverage percentage seems to be right (given some none coverage line that could not be seen)

So it clearly seems to be an issue on display in sonar and not an issue of the tool. The xml coverage files as the good format, the computation of line coverage seems good BUT on async C# method nothing is displayed :frowning:

Regards

Hello @Laurent

Could you please create a minimal reproducer project and share it with us (e.g. github repo)? Please mention in the README the commands that you are using.

This will help us jump on the topic quicker and kickstart the investigation.