1
votes

I am doing integration test using Arquillian in TomEE-Plus 7.0.4 remote and trying to get Code coverage using Jacoco 0.8.2. My code coverage is not covered since I am using arquillian-tomee-remote. Since code is not covered not able to take build. I need sample code with has TomEE-plus arquillian remote and Code coverage using Jacoco. I will appreciate if I get any sample working code or sample project.

I used prepare-agent goal which will generate surefireArgLine ( javaagent) and passed the same in surefire plugin. issue here is, I am using remote Tomee and don't know how to generate correct java agent surefireArgLine set to -javaagent:/home/user/.m2/repository/org/jacoco/org.jacoco.agent/0.8.2/org.jacoco.agent-0.8.2-runtime.jar=destfile=/home/user/project/target/coverage-reports/jacoco-ut.exec,append=true,excludes=/config/*.class:/util/*Constants.class

what is the correct javaagent option for my configuration which will connect to arquillian-remote-tomee ?

Jacoco plugin

    <plugin>
        <groupId>org.jacoco</groupId>
        <artifactId>jacoco-maven-plugin</artifactId>
        <version>${plugin.maven.jacoco.version}</version>
        <configuration>
            <propertyName>coverageAgent</propertyName>
            <append>true</append>
            <excludes>
                <exclude>**/config/*.class</exclude>
                <exclude>**/util/*Constants.class</exclude>
            </excludes>
        </configuration>
        <executions>
            <execution>
                <id>pre-unit-test</id>
                <goals>
                    <goal>prepare-agent</goal>
                </goals>
                <configuration>
                    <destFile>${sonar.jacoco.reportPath}</destFile>
                    <propertyName>surefireArgLine</propertyName>
                    <append>true</append>
                </configuration>
            </execution>
            <execution>
                <id>post-unit-test</id>
                <phase>test</phase>
                <goals>
                    <goal>report</goal>
                </goals>
                <configuration>
                    <dataFile>${sonar.jacoco.reportPath}</dataFile>
                    <outputDirectory>${project.reporting.outputDirectory}/jacoco-ut</outputDirectory>
                    <append>true</append>
                </configuration>
            </execution>
            <execution>
                <id>check</id>
                <goals>
                    <goal>check</goal>
                </goals>
                <configuration>
                    <dataFile>${sonar.jacoco.reportPath}</dataFile>
                    <haltOnFailure>true</haltOnFailure>
                    <rules>
                        <rule>
                            <element>BUNDLE</element>
                            <limits>
                                <limit>
                                    <counter>LINE</counter>
                                    <value>COVEREDRATIO</value>
                                    <minimum>0.99</minimum>
                                </limit>
                                <limit>
                                    <counter>BRANCH</counter>
                                    <value>COVEREDRATIO</value>
                                    <minimum>0.99</minimum>
                                </limit>
                                <limit>
                                    <counter>CLASS</counter>
                                    <value>MISSEDCOUNT</value>
                                    <maximum>0</maximum>
                                </limit>
                            </limits>
                        </rule>
                    </rules>
                </configuration>
            </execution>
        </executions>
    </plugin>

Dependency

<dependency>
    <groupId>org.jboss.arquillian.testng</groupId>
    <artifactId>arquillian-testng-container</artifactId>
    <scope>test</scope>
</dependency>

<dependency>
    <groupId>org.jboss.arquillian.config</groupId>
    <artifactId>arquillian-config-api</artifactId>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.jboss.arquillian.extension</groupId>
    <artifactId>arquillian-jacoco</artifactId>
    <version>1.0.0.Alpha10</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.jacoco</groupId>
    <artifactId>org.jacoco.agent</artifactId>
    <classifier>runtime</classifier>
    <scope>test</scope>
    <version>${plugin.maven.jacoco.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.jacoco/org.jacoco.core -->
<dependency>
    <groupId>org.jacoco</groupId>
    <artifactId>org.jacoco.core</artifactId>
    <version>${plugin.maven.jacoco.version}</version>
    <scope>test</scope>
</dependency>

<dependency>
    <groupId>org.apache.tomee</groupId>
    <artifactId>arquillian-tomee-remote</artifactId>
    <version>${tomee.version}</version>
    <scope>test</scope>
</dependency>

Arquillian.xml

<extension qualifier="jacoco">
    <property name="includes">com.demo.*</property>
</extension>
3

3 Answers

1
votes

You can set catalina_opts in arquillian.xml for tomee container. Filter it with maven to pass jacoco javaagent and you are done :).

1
votes

I have added the proper java agent ( surefireArgLine) to TomEE remote server via catalina opts in surefire pluggin. it works.

surefireArgLine - Will be populate by Surefire prepare-agent at runtime.

<tomee.catalina_opts> ${surefireArgLine}</tomee.catalina_opts>
-1
votes

Disclaimer: I'm not an expert in neither Arquillian nor TomEE, so you might adjust the answer for your purposes.

Anyway, in a nutshell, JaCoCo instruments bytecode in order to provide a coverage report.

Since when Arquillian is used, the actual test execution happens in a TomEE JVM and not in a JVM that actually runs the test suite (probably a CI server or just a build script that runs the test), so configuring JaCoCo on this test machine won't do much, you'll have to configure the server itself.

JaCoCo has a -javaagent option for doing this, and this Java Agent will "intercept" the loading of classes by the server and instrument them.

Now, when JaCoCo works, it produces a jacoco.exec file that actually contains a coverage report that can be shown later in various ways (jenkins plugin to show coverage, sonar integration whatever). And this is by far the most used option AFAIK, so if you go with this approach, given the instrumentation really works, after the tests are done, you'll have to find the server on the test machine and download it to the build machine and integrate with CI/Sonar whatever.

However, there are alternative solutions:

JaCoCo Documentation states that there are three modes of running an instrumenting Java Agent:

  • File System: At JVM termination execution data is written to a local file.
  • TCP Socket Server: External tools can connect to the JVM and retrieve execution data over the socket connection. Optional execution data reset and execution data dump on VM exit is possible.
  • TCP Socket Client: At startup, the JaCoCo agent connects to a given TCP endpoint. Execution data is written to the socket connection on request. Optional execution data reset and execution data dump on VM exit is possible.

Technically you can just give different parameters to that javaagent so that it will run JaCoCo in one of these modes.

Anyway, we've discussed the first option, but you can also work with TCP configurations if it's required. Of course, here you'll have to handle security concerns (like permission to expose/access the port, etc).

If you work with TCP mode, there is a Maven Plugin that can come in handy. I haven't used it by myself, just googled so I can't comment whether its any good, it has only 2 stars on Github, so probably it's not production ready but maybe you could get some ideas from its source code.