Search code examples
groovyjacocojacoco-maven-plugingroovyshell

Can JaCoCo instrument groovy scripts?


I'm trying to instrument groovy scripts with JaCoCo, but it seems that JaCoCo can only instrument groovy classes. I can see the scripts in the report, but it always shows them with 0% of coverage. I'm using GroovyShell to execute the scripts in the tests. It seems that because of the way that the scripts are executed, JaCoCo cannot match the source code with the tests.

This is my JaCoCo configuration:

dependency>
    <groupId>org.jacoco</groupId>
    <artifactId>org.jacoco.agent</artifactId>
    <classifier>runtime</classifier>
    <scope>test</scope>
    <version>0.8.7</version>
</dependency>

<plugin>
    <groupId>org.jacoco</groupId>
    <artifactId>jacoco-maven-plugin</artifactId>
    <version>0.8.7</version>
    <executions>
        <execution>
            <id>default-instrument</id>
            <goals>
                <goal>instrument</goal>
            </goals>
        </execution>
        <execution>
            <id>default-restore-instrumented-classes</id>
            <goals>
                <goal>restore-instrumented-classes</goal>
            </goals>
        </execution>
        <execution>
            <id>report</id>
            <phase>prepare-package</phase>
            <goals>
                <goal>report</goal>
            </goals>
        </execution>
    </executions>
</plugin>
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <configuration>
        <systemPropertyVariables>
            <jacoco-agent.destfile>target/jacoco.exec</jacoco-agent.destfile>
        </systemPropertyVariables>
    </configuration>
</plugin>

Solution

  • JaCoCo can instrument groovy scripts.

    It is not necessary to use offline instrumentation.

    JaCoCo was unable to match the files because I was compiling the scripts, but when the scripts are executed, the GroovyShell compiles them again generating other byte codes with different class Ids. JaCoCo uses the class Ids to match the classes executed and the classes analyzed. The workaround for that is to make the JaCoCo agent dump the files processed under the target folder, then we'll have the same class Ids and everything will work fine.

    With this approach, JaCoCo will generate reports for all the libraries as well. To avoid that, we need to specify which packages we want to instrument.

    We also need to remove the compile goal from the gmavenplus-plugin, otherwise the scripts will be compiled twice and JaCoCo will throw an error for duplicate classes name.

    This is my final pom configuration:

    <plugin>
        <groupId>org.codehaus.gmavenplus</groupId>
        <artifactId>gmavenplus-plugin</artifactId>
        <version>1.12.1</version>
        <executions>
            <execution>
                <goals>
                    <goal>addSources</goal>
                    <goal>addTestSources</goal>
                    <!-- <goal>compile</goal>-->
                    <goal>compileTests</goal>
                </goals>
            </execution>
        </executions>
        ...
    </plugin>
    
    
    <plugin>
        <groupId>org.jacoco</groupId>
        <artifactId>jacoco-maven-plugin</artifactId>
        <version>0.8.7</version>
        <executions>
            <execution>
                <goals>
                    <goal>prepare-agent</goal>
                </goals>
                <configuration>
                    <classDumpDir>target/classes</classDumpDir>
                    <includes>
                        <include>packageToInclude/**</include>
                    </includes>
                </configuration>
            </execution>
            <execution>
                <id>report</id>
                <phase>prepare-package</phase>
                <goals>
                    <goal>report</goal>
                </goals>
            </execution>
        </executions>
    </plugin>
    

    Further reading about the classes Ids: https://www.eclemma.org/jacoco/trunk/doc/classids.html Further reading about dumping class files: https://www.jacoco.org/jacoco/trunk/doc/agent.html