Skip to content

Inline coverage not interpreting Cobertura source path

Summary

I'm trying to gather code coverage on a PHP project using PHPUnit's Cobertura reporter. However, I can only get the inline coverage visualizations to appear if the <source> element contains just the repository root and the filename for each covered class exactly matches the full path within the repository.

For example, assume we have a repository with the following files:

  • src/Foo/Bar.php
  • src/Baz.php
  • public/index.php

When checked out on my CI runner they might live at paths like:

  • /builds/my/project/src/Foo/Bar.php
  • /builds/my/project/src/Baz.php
  • /builds/my/project/public/index.php

When PHPUnit creates the cobertura coverage report, it sets the source to whatever path the covered classes have in common. The individual filename is then set to the full absolute path minus that shared <source> path For example:

Files Tested Reduced <source> path Individual filename paths
src/Foo/Bar.php /builds/my/project/src/Foo Bar.php
src/Foo/Bar.php and src/Baz.php /builds/my/project/src Foo/Bar.php and Baz.php
All three files /builds/my/project src/Foo/Bar.php, src/Baz.php, public/index.php

I only see inline coverage data rendered in the MR in that last case. When that happens, the cobertura XML file looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE coverage SYSTEM "http://cobertura.sourceforge.net/xml/coverage-04.dtd">
<coverage line-rate="0.0032243618450515" branch-rate="0" lines-covered="36" lines-valid="11165" branches-covered="0" branches-valid="0" complexity="4498" version="0.4" timestamp="1609110724">
  <sources>
    <source>/builds/my/project</source>
  </sources>
  <packages>
    <package name="" line-rate="0" branch-rate="0" complexity="11">
      <classes>
        <class name="App\Foo\Bar" filename="src/Foo/Bar.php" line-rate="0" branch-rate="0" complexity="11">
          <methods>
<!-- output truncated -->

Steps to reproduce

Provide a cobertura coverage report where <source> contains a subpath:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE coverage SYSTEM "http://cobertura.sourceforge.net/xml/coverage-04.dtd">
<coverage line-rate="0.0032243618450515" branch-rate="0" lines-covered="36" lines-valid="11165" branches-covered="0" branches-valid="0" complexity="4498" version="0.4" timestamp="1609110724">
  <sources>
    <source>/builds/my/project/src</source>
  </sources>
  <packages>
    <package name="" line-rate="0" branch-rate="0" complexity="11">
      <classes>
        <class name="App\Foo\Bar" filename="Foo/Bar.php" line-rate="0" branch-rate="0" complexity="11">
          <methods>
<!-- output truncated -->

Search for <source> and filename in the two examples above and you'll see what I mean.

What is the current bug behavior?

No inline code coverage appears in the MR.

What is the expected correct behavior?

Ideally: Inline code coverage should appear

Not ideal but better than nothing: Gitlab should give some kind of warning/error that it couldn't map the coverage data to repo files

Possible fixes

I think Gitlab needs to concatenate the <source> and filename together (with a / in between) to determine the absolute path and then use its knowledge of where CI checked the file out to trim that part off the left side.

In other words, given all of these three possibilities...

<source> filename
/builds/my/project/src/Foo Bar.php
/builds/my/project/src Foo/Bar.php
/builds/my/project src/Foo/Bar.php

... Gitlab should interpret the file path as src/Foo/Bar.php

Issue #233144 might be related since it deals with <source> paths but I'm honestly not sure. Regardless, I think this issue here should be considered a ~bug and not a feature since the coverage report seems accurate (and PHPUnit's path outputs make sense) but Gitlab is failing to interpret those paths.

Edited by Colin O'Dell