Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cobertura: Line coverage is incomplete for Jest-generated coverages #603

Closed
RoadTrain opened this issue Apr 12, 2023 · 8 comments
Closed

Comments

@RoadTrain
Copy link

RoadTrain commented Apr 12, 2023

Describe the bug
When parsing Cobertura files generated with JestJS some line coverage information is not processed by ReportGenerator. Apparently, ReportGenerator only considers line coverage information attached to <class> element while ignoring information attached to <method> elements.

It works for other cobertura producers because they usually duplicate line coverage: so a line is attached to both a class and a method. In case with JestJS it's not duplicated for some unknown reason, so a line is attached to either a class or a method.

To Reproduce
Try to generate a report from this example:

<?xml version="1.0" ?>
<!DOCTYPE coverage SYSTEM "http://cobertura.sourceforge.net/xml/coverage-04.dtd">
<coverage lines-valid="7" lines-covered="2" line-rate="0.28" branches-valid="0" branches-covered="0" branch-rate="0" timestamp="1681280730343" complexity="0" version="0.1">
  <sources>
    <source>C:\coverage</source>
  </sources>
  <packages>
    <package name="some.package.name" line-rate="0.5" branch-rate="0">
      <classes>
        <class name="code-file.js" filename="src\code-file.js" line-rate="0.5" branch-rate="0">
          <methods>
            <method name="(anonymous_0)" hits="0" signature="()V">
              <lines>
                <line number="4" hits="0"/>
              </lines>
            </method>
            <method name="(anonymous_1)" hits="0" signature="()V">
              <lines>
                <line number="8" hits="0"/>
              </lines>
            </method>
            <method name="(anonymous_2)" hits="0" signature="()V">
              <lines>
                <line number="11" hits="0"/>
              </lines>
            </method>
          </methods>
          <lines>
            <line number="1" hits="3" branch="false"/>
            <line number="3" hits="3" branch="false"/>
            <line number="5" hits="0" branch="false"/>
            <line number="9" hits="0" branch="false"/>
          </lines>
        </class>
      </classes>
    </package>
  </packages>
</coverage>

Expected result:
Covered = 2
Uncovered = 5
Coverable = 7
Actual result:
image

@RoadTrain
Copy link
Author

The code in question seems to be located here:

var lines = classes.Elements("lines")
.Elements("line")
.ToArray();

A straightforward solution would be to parse lines data for both classes and methods but then make sure to filter out duplicates in the resulting line set.

@RoadTrain
Copy link
Author

RoadTrain commented Apr 13, 2023

Here's an chunk of cobertura produced by coverlet:

        <class name="SomeClass" filename="SomeClass.cs" line-rate="1" branch-rate="1" complexity="2">
          <methods>
            <method name="get_RepoPath" signature="()" line-rate="1" branch-rate="1" complexity="1">
              <lines>
                <line number="5" hits="5" branch="False" />
              </lines>
            </method>
            <method name="get_CovPath" signature="()" line-rate="1" branch-rate="1" complexity="1">
              <lines>
                <line number="7" hits="3" branch="False" />
              </lines>
            </method>
          </methods>
          <lines>
            <line number="5" hits="5" branch="False" />
            <line number="7" hits="3" branch="False" />
          </lines>
        </class>

Notice how line data is duplicated, so only looking at class-level data would be enough here. But it's not enough for Jest-produced coverages.

@danielpalme
Copy link
Owner

Thanks for your detailed description.

I will try to add a workaround in ReportGenerator with the next days.

Why does Jest do it differently as everyone else ...

@RoadTrain
Copy link
Author

Yeah, it's annoying. I think it's probably in part due to a lack of a formal cobertura standard.

@RoadTrain
Copy link
Author

RoadTrain commented Apr 13, 2023

I took another look at jest cobertura, and apparently there's always one <line> element for a <method> -- it's the line where method name is declared (like function name(...) {). And the lines for the method body are at <class>.
This makes it even weirder.

The bad side effect of this is that ReportGenerator cannot correctly determine first and last line of a method.

@danielpalme
Copy link
Owner

I made the necessary changes in d472d5d.

The only problem that remains is, that "ReportGenerator cannot correctly determine first and last line of a method".
But there's nothing I can do about that.

Next release will contain the changes. I guess a new version will be published within the next 1-2 weeks.

@danielpalme
Copy link
Owner

Release 5.1.20 is now available!

@RoadTrain
Copy link
Author

RoadTrain commented Apr 28, 2023

@danielpalme Thanks, will try soon!

Regarding

ReportGenerator cannot correctly determine first and last line of a method

I have found the exact place where this incomplete cobertura is generated, for future reference: https://github.com/istanbuljs/istanbuljs/blob/master/packages/istanbul-reports/lib/cobertura/index.js#L102

I am planning to file an issue at istanbuljs, but apparently that project has been inactive since Nov 2022.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants