Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Tomcat7 Maven Plugin and JaCoCo

Is there any way to get code coverage using JaCoCo with the tomcat7-maven-plugin embedded instance?

The jacoco-maven-plugin is configured in my WAR's POM to instrument my unit tests, but I'm not sure how to attach the jacoco agent to the embedded Tomcat instance to instrument my integration tests that run against Tomcat. Given that the Tomcat instance is embedded, I'm not sure if this approach is possible. Is there any other way to accomplish this? I can probably switch from using the Tomcat Maven Plugin to using Cargo to get coverage, but I'd prefer to stick with the Tomcat plugin if possible.

Here are a few relevant snippets from my POM:

<plugin>
    <groupId>org.jacoco</groupId>
    <artifactId>jacoco-maven-plugin</artifactId>
    <version>0.6.2.201302030002</version>
    <executions>
        <execution>
            <goals>
                <goal>prepare-agent</goal>
            </goals>
        </execution>
    </executions>
</plugin>
<plugin>
    <artifactId>maven-failsafe-plugin</artifactId>
    <version>2.14</version>
    <executions>
        <execution>
            <id>integration-tests</id>
            <goals>
                <goal>integration-test</goal>
                <goal>verify</goal>
            </goals>
        </execution>
    </executions>
</plugin>
<plugin>
    <groupId>org.apache.tomcat.maven</groupId>
    <artifactId>tomcat7-maven-plugin</artifactId>
    <version>2.1</version>
    <configuration>
        <systemProperties>
            <!-- as expected, this system property doesn't work since Tomcat is embedded, but this is the type of config I'm looking for -->
            <JAVA_OPTS>-javaagent:${project.build.directory}/${jacoco.jar}=destfile=${project.build.directory}/jacoco.exec,append=true</JAVA_OPTS>
        </systemProperties>
    </configuration>
    <executions>
        <execution>
            <id>tomcat-startup</id>
            <goals>
                <goal>run-war-only</goal>
            </goals>
            <phase>pre-integration-test</phase>
            <configuration>
                <fork>true</fork>
            </configuration>
        </execution>
        <execution>
            <id>tomcat-shutdown</id>
            <goals>
                <goal>shutdown</goal>
            </goals>
            <phase>post-integration-test</phase>
        </execution>
    </executions>
</plugin>

Versions: Maven 3.0.4, Tomcat Maven Plugin 2.1, Jacoco 0.6.2.201302030002, Java 7

like image 537
shelley Avatar asked Apr 15 '13 15:04

shelley


People also ask

What is Tomcat7 Maven plugin?

The Tomcat7 Maven Plugin provides goals to manipulate WAR projects within the Tomcat servlet container version 7.x.

What does JaCoCo Maven plugin do?

The JaCoCo-Maven plugin runs the coverage by instrumenting Java code through a runtime agent. In simple terms, you attach this agent to a JVM (Java Virtual Machine) when it starts. This agent is termed as JaCoCo agent. The first execution start-agent starts this JaCoCo Runtime Agent.

How do you use JaCoCo for code coverage in Maven?

Run the mvn package command. The package command will invoke the test phase during the packaging of the project jar or war file. In the test phase, JaCoCo agent will initialize and run the code coverage analysis while the tests are executed.

Does JaCoCo work with Java 11?

JaCoCo now officially supports Java 11 (GitHub #760). Experimental support for Java 13 class files (GitHub #835). Branch added by the Kotlin compiler for "unsafe" cast operator is filtered out during generation of report (GitHub #761).


2 Answers

I know its been awhile since the question was posted but I don't feel the answer really addressed the root of the problem. Code coverage may work with failsafe or surefire if you are running tests within those plugins. However, if you just want to monitor tomcat with jacoco to get a coverage report current information doesn't provide that. I found that the tomcat7-maven-plugin doesn't allow you to inject the -javaagent for jacoco by simply providing JAVA_OPTS. Switching to cargo I was able to do that like so.

<plugin>
    <groupId>org.jacoco</groupId>
    <artifactId>jacoco-maven-plugin</artifactId>
    <version>0.7.2.201409121644</version>
    <configuration>
        <destFile>${sonar.jacoco.reportPath}</destFile>
        <dataFile>${sonar.jacoco.reportPath}</dataFile>
        <outputDirectory>${project.reporting.outputDirectory}/jacoco-it</outputDirectory>
        <classDumpDir>${project.reporting.outputDirectory}/jacoco-it/classes</classDumpDir>
        <skip>${skipITs}</skip>
    </configuration>
    <executions>
        <execution>
            <id>jacoco-agent</id>
            <phase>pre-integration-test</phase>
            <goals>
                <goal>prepare-agent</goal>
            </goals>
            <configuration>
                <destFile>${sonar.jacoco.reportPath}</destFile>
                <propertyName>jacoco.agent.itArgLine</propertyName>
            </configuration>
        </execution>
        <execution>
            <id>jacoco-report</id>
            <phase>post-integration-test</phase>
            <goals>
                <goal>dump</goal>
                <goal>report</goal>
            </goals>
        </execution>
    </executions>
</plugin>
    <plugin>
    <groupId>org.codehaus.cargo</groupId>
    <artifactId>cargo-maven2-plugin</artifactId>
    <version>1.4.11</version>
    <configuration>
        <skip>${skipITs}</skip>
        <container>
            <containerId>tomcat7x</containerId>
            <zipUrlInstaller>
                <url>http://archive.apache.org/dist/tomcat/tomcat-7/v7.0.16/bin/apache-tomcat-7.0.16.zip
                </url>
                <downloadDir>${project.build.directory}/downloads</downloadDir>
                <extractDir>${project.build.directory}/extracts</extractDir>
            </zipUrlInstaller>
            <dependencies>
                <dependency>
                    <groupId>ojdbc</groupId>
                    <artifactId>ojdbc6</artifactId>
                </dependency>
            </dependencies>
        </container>
        <configuration>
            <home>${project.build.directory}/catalina-base</home>
            <properties>
                <cargo.jvmargs>${jacoco.agent.itArgLine},output=tcpserver,port=6300 -Drunmode=TEST</cargo.jvmargs>
                <cargo.servlet.port>9090</cargo.servlet.port>
            </properties>
            <configfiles>
                <configfile>
                    <file>${basedir}/src/test/conf/context.xml</file>
                    <todir>conf/Catalina/localhost/</todir>
                    <tofile>context.xml.default</tofile>
                </configfile>
            </configfiles>
        </configuration>
    </configuration>
    <executions>
        <execution>
            <id>start-tomcat</id>
            <phase>pre-integration-test</phase>
            <goals>
                <goal>start</goal>
            </goals>
        </execution>
        <execution>
            <id>stop-tomcat</id>
            <phase>post-integration-test</phase>
            <goals>
                <goal>stop</goal>
            </goals>
        </execution>
    </executions>
</plugin>

the important parts are:

  1. <plugin><groupId>org.jacoco</groupId> ...<propertyName>jacoco.agent.itArgLine</propertyName>
  2. <cargo.jvmargs>${jacoco.agent.itArgLine},output=tcpserver,port=6300 </cargo.jvmargs>

When report target is run on the jacoco plugin it will create a directory in ${projectbase}/target/site/jacoco-it/index.html with your coverage report. I use this with the soapui-maven-plugin but it could be used with selenium-maven-plugin also.

like image 146
Koder Avatar answered Oct 27 '22 00:10

Koder


You don't need pass JAVA_OPTS to tomcat embedded if you use maven-failsafe-plugin (or maven-surefire-plugin) to run yours integration test. It is because tomcat embedded run in the same process of maven-failsafe-plugin.

So when jacoco-maven-plugin execute prepare-agent it sets argLine that maven-failsafe-plugin uses too.

I created a project to test this, below part of pom:

<build>
    <plugins>
        <plugin>
            <groupId>org.jacoco</groupId>
            <artifactId>jacoco-maven-plugin</artifactId>
            <version>0.6.2.201302030002</version>
            <executions>
                <execution>
                    <goals>
                        <goal>prepare-agent</goal>
                    </goals>
                    <configuration>
                        <includes>
                            <include>my.project.package.only.*</include>
                        </includes>
                    </configuration>
                </execution>
            </executions>
        </plugin>
        <plugin>
            <groupId>org.apache.tomcat.maven</groupId>
            <artifactId>tomcat7-maven-plugin</artifactId>
            <version>2.1</version>
            <executions>
                <execution>
                    <id>tomcat-startup</id>
                    <goals>
                        <goal>run-war-only</goal>
                    </goals>
                    <phase>pre-integration-test</phase>
                    <configuration>
                        <fork>true</fork>
                    </configuration>
                </execution>
                <execution>
                    <id>tomcat-shutdown</id>
                    <goals>
                        <goal>shutdown</goal>
                    </goals>
                    <phase>post-integration-test</phase>
                </execution>
            </executions>
        </plugin>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-failsafe-plugin</artifactId>
            <executions>
                <execution>
                    <id>integration-tests</id>
                    <phase>integration-test</phase>
                    <goals>
                        <goal>integration-test</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
        <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>selenium-maven-plugin</artifactId>
            <version>2.3</version>
            <executions>
                <execution>
                    <id>start</id>
                    <phase>pre-integration-test</phase>
                    <goals>
                        <goal>start-server</goal>
                    </goals>
                    <configuration>
                        <background>true</background>
                        <logOutput>true</logOutput>
                        <multiWindow>true</multiWindow>
                    </configuration>
                </execution>
                <execution>
                    <id>stop</id>
                    <phase>post-integration-test</phase>
                    <goals>
                        <goal>stop-server</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins> 
like image 32
Andre Piantino Avatar answered Oct 26 '22 23:10

Andre Piantino