Skip to content

Cobertura output async "class" merging can create duplicate method entries #630

@Malivil

Description

@Malivil

Describe the bug
When using reportgenerator to output a Cobertura report, classes with async method overrides with the same name will have duplicate entries in the generated XML.

For example, this MVC controller code:

public class TestController : Controller
{
    public ActionResult Index()
    {
        return View();
    }

    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<ActionResult> Index([FromForm] IFormFile file)
    {
        return View();
    }
}

Generates this XML using Coverlet:

<?xml version="1.0" encoding="utf-8"?>
<coverage line-rate="0.2727" branch-rate="0" version="1.9" timestamp="1696950298" lines-covered="6" lines-valid="22" branches-covered="0" branches-valid="2">
  <sources>
    <source></source>
  </sources>
  <packages>
    <package name="CoverletRepro" line-rate="0.2727" branch-rate="0" complexity="4">
      <classes>
        <class name="CoverletRepro.TestController" filename="TestController.cs" line-rate="1" branch-rate="1" complexity="1">
          <methods>
            <method name="Index" signature="()" line-rate="1" branch-rate="1" complexity="1">
              <lines>
                <line number="8" hits="1" branch="False" />
                <line number="9" hits="1" branch="False" />
                <line number="10" hits="1" 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="False" />
          </lines>
        </class>
        <class name="CoverletRepro.TestController/&lt;Index&gt;d__1" filename="TestController.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>
      </classes>
    </package>
  </packages>
</coverage>

If that XML file is then fed into reportgenerator, it creates this XML file:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE coverage SYSTEM "http://cobertura.sourceforge.net/xml/coverage-04.dtd">
<coverage line-rate="1" branch-rate="1" lines-covered="6" lines-valid="6" branches-covered="0" branches-valid="0" complexity="2" version="0" timestamp="1696936548">
  <sources>
    <source></source>
  </sources>
  <packages>
    <package name="CoverletRepro" line-rate="1" branch-rate="1" complexity="2">
      <classes>
        <class name="CoverletRepro.TestController" filename="TestController.cs" line-rate="1" branch-rate="1" complexity="2">
          <methods>
            <method name="Index" signature="()" line-rate="1" branch-rate="1" complexity="1">
              <lines>
                <line number="8" hits="1" branch="false" />
                <line number="9" hits="1" branch="false" />
                <line number="10" hits="1" branch="false" />
              </lines>
            </method>
            <method name="Index" 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="8" hits="1" branch="false" />
            <line number="9" hits="1" branch="false" />
            <line number="10" hits="1" branch="false" />
            <line number="15" hits="1" branch="false" />
            <line number="16" hits="1" branch="false" />
            <line number="17" hits="1" branch="false" />
          </lines>
        </class>
      </classes>
    </package>
  </packages>
</coverage>

Which has two "Index" entries with the same empty signature.
I'm not sure if this is a limitation of the format, a problem with Coverlet, or a problem with reportgenerator but as it only occurs after running through reportgenerator I thought I would start here.

To Reproduce
The following input helps to reproduce your issue:

  1. Download coverage.cobertura.txt and TestController.txt from this issue. Both extensions were changed so GitHub would support them
  2. Run latest reportgenerator like so: reportgenerator "-reports:coverage.cobertura.txt" "-targetdir:." "-reporttypes:Cobertura"
  3. See XML like the last code block above

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions