JaCoCo does not show the source files in the HTML coverage report for multi projects
Asked Answered
V

2

11

I'm using PDE and in my build.xml I compile my code and try to create a coverage report using JaCoCo and JUnit. I noticed that it does now show the sourcefile, even though I added sourcefiles section in the structure section of jacoco:report. In order to debug it (because it does not prints any errors), I tried to run it locally:

java -jar jacoco/jacococli.jar report /buildFiles/coverage/jacoco.exec --classfiles /buildFiles/plugins/com.gandu.da.util.test/bin/com/gandu/da/util/test/AllTests.class --sourcefiles /buildFiles/plugins/com.gandu.da.util.test/src/com/gandu/da/util/test/AllTests.java --html html_report

But it still does not show the sourcecode in the html file. In the official JaCoCo FAQ I see:

Why does the coverage report not show highlighted source code? Make sure the following prerequisites are fulfilled to get source code highlighting in JaCoCo coverage reports:

  • Class files must be compiled with debug information to contain line numbers.
  • Source files must be properly supplied at report generation time. I.e. specified source folders must be the direct parent of the folders that define the Java packages.

I compiled the code with -g flag to get all the information - it didn't work. Also I believe that I do supply the src/bin files as expected so I'm not sure why it does not work. How to make it work?

EDIT: I had to provide the src directory:

java -jar jacoco/jacococli.jar report /buildFiles/coverage/jacoco.exec --classfiles /buildFiles/plugins/com.gandu.da.util.test/bin/com/gandu/da/util/test/AllTests.class --sourcefiles /buildFiles/plugins/com.gandu.da.util.test/src
# WORKED!

Now I want to fix the issue with my build.xml. The code:

<jacoco:report>
    <executiondata>
        <file file="${coverage.file}"/>
    </executiondata>
    <structure name="Coverage Report">
        <classfiles>
            <fileset dir="${buildDirectory}/plugins/com.gandu.da.util.test/bin">
                <include name="**/*.class" />
            </fileset>
        </classfiles>
        <sourcefiles encoding="UTF-8">
            <fileset dir="${buildDirectory}/plugins/com.gandu.da.util.test/src">
                <include name="**/*.java" />
            </fileset>
        </sourcefiles>
    </structure>
    
    <html destdir="${coverage.html}"/>
</jacoco:report>

This code worked and it provided the coverage report with the source files. But as you can see I had to hardcoded only one package (com.gandu.da.util.test). I want to create a coverage report from all the packages that:

  • src: ${buildDirectory}/plugins/com.gandu*/src.
  • bin: ${buildDirectory}/plugins/com.gandu*/bin.

So I tried:

<jacoco:report>
    <executiondata>
        <file file="${coverage.file}"/>
    </executiondata>
    <structure name="Coverage Report">
        <classfiles>
            <fileset dir="${buildDirectory}/plugins/com.gandu.*/bin">
                <include name="**/*.class" />
            </fileset>
        </classfiles>
        <sourcefiles encoding="UTF-8">
            <fileset dir="${buildDirectory}/plugins/com.gandu.*/src">
                <include name="**/*.java" />
            </fileset>
        </sourcefiles>
    </structure>
    
    <html destdir="${coverage.html}"/>
</jacoco:report>

But it didn't work because the path (with the star) does not exist. It makes sense because dir expects to get one path. So I figured that <foreach> might help here but after reading the docs, I could not figure a way to use it. The above code is what I need. I hope to hear a suggestion on how to solve this.

One more note since it's important: the structure of source and class files:

  • source files are located under ${buildDirectory}/plugins/com.gandu*/src.
  • class files are located under: ${buildDirectory}/plugins/com.gandu*/bin.

I also tried to insert ${buildDirectory}/plugins in dir of both <classfiles> and <sourcefiles> but it didn't work. It does create the coverage report but it does not show the source files. I guess I need to provide the src dir of each package.

So I thought to use <foreach> to insert each package into the structure. I might need to use jacoco:merge to merge them, but I'm not sure.

Also tried includes="**/usr/** and includes="**/bin/**.

I also have a few different ant version I could use here. might help? Also, maybe I could "hardcode" the plugins somehow and "merge" the reports?

EDIT: It looked like it worked when you provide multi plugins like so:

<jacoco:report>
    <!--  This task needs the collected execution data and ...  -->
    <executiondata>
        <file file="${coverage.metadata.file}"/>
    </executiondata>
    <!--  the class files and optional source files ...  -->
    <structure name="JaCoCo Coverage Report">
        <classfiles>
            <fileset dir="${buildDirectory}/plugins/com.gandu.da.util.mangager.test/@dot">
                 <include name="**/*.class" />
            </fileset>
            <fileset dir="${buildDirectory}/plugins/com.gandu.da.util.alltests/@dot">
                 <include name="**/*.class" />
            </fileset>
        </classfiles>
        <sourcefiles encoding="UTF-8">
            <fileset dir="${buildDirectory}/plugins/com.gandu.da.util.mangager.test/src">
                <include name="**/*.java" />
            </fileset>
            <fileset dir="${buildDirectory}/plugins/com.gandu.da.util.alltests/src">
                <include name="**/*.java" />
            </fileset>
        </sourcefiles>
    </structure>
    
    <html destdir="${coverage.html.dir}"/>
    <csv destfile="${coverage.csv.file}"/>
    <xml destfile="${coverage.xml.file}"/>
</jacoco:report>

Is it possible to maybe put all the wanted names (like com.gandu.da.util.alltests) into a file, read them one by one, and run for (or foreach) on them and add them as fileset maybe (after you append each one with the path)?

Vano answered 30/8, 2021 at 16:19 Comment(6)
It's not that this answers the question, but have you already considered using a more modern build management tool like e.g. Maven (or if you really must Gradle)? There would be the JaCoCo Maven Plug-in which works in a (n>1)⋅10⁵ LOC project here like a charm.Adlib
@GeroldBroser Unfortunately it's a legacy tool which needed PDE and Eclipse 4.8 (its built on Eclipse) so it's not possible to move to Maven/Gradle at the moment.Vano
It have been a few days since I added the bounty. Maybe I need to add additional information for you? Just let me know in the commentsVano
Your title and the first few paragraphs still reflect your first question, about including source files, but I think you are now asking a second question about including multiple projects in a single JaCoCo report, right? You might get better answers if you cleared that up. GL!Scevour
@Scevour its the same project but I have a few packages in that project. All start with /com.gandu.*. My first question was about the JaCoCo CLI because I described the issue in the first paragraph and it was a debugging attempt. Thank you for the comment!Vano
could you run ant with diagnostic flags- it will print more information why particular directory is not seen.Bout
C
2

The issue is not meeting one of the declared preconditions:

specified source folders must be the direct parent of the folders that define the Java packages

--sourcefiles /buildFiles/plugins/com.gandu.da.util.test/src

Gradle might be a whole lot more script-able than the CLI or Maven is.

Comatose answered 13/9, 2021 at 16:55 Comment(0)
J
0

Try ensuring that your includes are handled correctly by changing:

<include name="**/*.class" />

...to...

includes ="**/*.class"

...and...

<include name="**/*.java" />

...to...

includes ="**/*.java"

PS: Having trouble with the editor accepting each alternate in code brackets.

Jackal answered 13/9, 2021 at 17:2 Comment(1)
I tried it but it didn't solve the issue. Still does not show the source files in the coverage report.Vano

© 2022 - 2024 — McMap. All rights reserved.