Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Maven JaCoCo plugin error

Tags:

I have configured the Maven JaCoCo plugin as follows in my pom.xml file:

<properties>     <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>     <jacoco.version>0.5.9.201207300726</jacoco.version> </properties>  <profiles>     <profile>         <id>jacoco4</id>         <build>             <plugins>                 <plugin>                     <groupId>org.jacoco</groupId>                     <artifactId>jacoco-maven-plugin</artifactId>                     <version>${jacoco.version}</version>                     <executions>                         <execution>                             <goals>                                 <goal>prepare-agent</goal>                             </goals>                             <configuration                             <destfile>${project.build.directory}/target/jacoco.exec</destfile>                             <datafile>${project.build.directory}/target/jacoco.exec</datafile>                                 <output>file</output>                                 <append>true</append>                             </configuration>                         </execution>                         <execution>                             <id>report</id>                             <phase>prepare-package</phase>                             <goals>                                 <goal>report</goal>                             </goals>                         </execution>                     </executions>                 </plugin>             </plugins>         </build>     </profile> </profiles> 

I'm using Windows 7 and the apache-maven-3.0.4 plugin. When I type mvn -P jacoco4 install, either from a cygwin terminal or from a command prompt terminal, Maven downloads and runs the JaCoCo plugin, but then the jacoco.exec file doesn't appear to have been created. Below is the error message:

[ERROR] Unable to read execution data file C:\Users\brownru\workspace64new\vps9\vps-fileserver\target\jacoco.exec: C:\Users\brownru\workspace64new\vps9\vps-fileserver\target\jacoco.exec (The system cannot find the file specified) java.io.FileNotFoundException: C:\Users\brownru\workspace64new\vps9\vps-fileserver\target\jacoco.exec (The system cannot find the file specified)         at java.io.FileInputStream.open(Native Method)         at java.io.FileInputStream.<init>(FileInputStream.java:120)         at org.jacoco.maven.ReportMojo.loadExecutionData(ReportMojo.java:251)         at org.jacoco.maven.ReportMojo.executeReport(ReportMojo.java:228)         at org.jacoco.maven.ReportMojo.execute(ReportMojo.java:217)         at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:101)         at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:209)         at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:153)         at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:145)         at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:84)         at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:59)         at org.apache.maven.lifecycle.internal.LifecycleStarter.singleThreadedBuild(LifecycleStarter.java:183)         at org.apache.maven.lifecycle.internal.LifecycleStarter.execute(LifecycleStarter.java:161)         at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:320)         at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:156)         at org.apache.maven.cli.MavenCli.execute(MavenCli.java:537)         at org.apache.maven.cli.MavenCli.doMain(MavenCli.java:196)         at org.apache.maven.cli.MavenCli.main(MavenCli.java:141)         at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)         at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)         at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)         at java.lang.reflect.Method.invoke(Method.java:597)         at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced(Launcher.java:290)         at org.codehaus.plexus.classworlds.launcher.Launcher.launch(Launcher.java:230)         at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode(Launcher.java:409)         at org.codehaus.plexus.classworlds.launcher.Launcher.main(Launcher.java:352) 

This error message appears whether or not I include the destfile and datafile specifiers in the configuration of the plugin:

<destfile>${project.build.directory}/target/jacoco.exec</destfile> <datafile>${project.build.directory}/target/jacoco.exec</datafile> 

Can someone please tell me what I'm doing wrong?

like image 284
kirigiri Avatar asked Sep 04 '12 18:09

kirigiri


People also ask

Why does JaCoCo not show coverage?

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.

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.

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).

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.


2 Answers

I had the same trouble with jacoco and maven. It was related to a parent pom overwriting the configuration of surefire. In this case, that plugin didn't used the argument (for jvm argument) defining the agent.

The solution was to put the "argLine" configuration element back

<plugin>   <artifactId>maven-surefire-plugin</artifactId>   <configuration>    <argLine>${argLine}</argLine>   </configuration>  </plugin> 

Full plugin conf looks like

<plugin>   <artifactId>maven-surefire-plugin</artifactId>   <configuration>     <skip>true</skip>   </configuration>   <executions>     <execution>       <id>unit-test</id>       <phase>test</phase>       <goals>         <goal>test</goal>       </goals>       <configuration>         <skip>${maven.test.skip}</skip>         <argLine>${argLine}</argLine>         <excludes>           <exclude>**/*IntegrationTest.java</exclude>         </excludes>       </configuration>     </execution>     <execution>       <id>integration-test</id>       <phase>integration-test</phase>       <goals>         <goal>test</goal>       </goals>       <configuration>         <skip>${skipITs}</skip>         <argLine>${argLine}</argLine>         <includes>           <include>**/*IntegrationTest.java</include>         </includes>       </configuration>     </execution>   </executions> </plugin> <plugin>     <groupId>org.jacoco</groupId>     <artifactId>jacoco-maven-plugin</artifactId>     <version>0.5.10.201208310627</version>     <configuration>         <skip>${maven.test.skip}</skip>         <destFile>${basedir}/target/coverage-reports/jacoco-unit.exec</destFile>         <dataFile>${basedir}/target/coverage-reports/jacoco-unit.exec</dataFile>         <output>file</output>         <append>true</append>     </configuration>     <executions>         <execution>             <id>jacoco-initialize</id>             <goals>                 <goal>prepare-agent</goal>             </goals>         </execution>         <execution>             <id>jacoco-site</id>             <phase>verify</phase>             <goals>                 <goal>report</goal>             </goals>         </execution>     </executions> </plugin> 

Hope it'll be usefull

like image 113
Sylvain Avatar answered Sep 29 '22 19:09

Sylvain


OK I think I figured out what is going on.

By default, the jacoco plugin "runs" before the test phase (typically it runs the prepare-agent goal during the initialize lifecycle phase), and when it runs, it just sets a maven property called "argLine" to something like -javaagent=jacoco.jar

ex:

[INFO] argLine set to -javaagent:/usernamed/.m2/repository/org/jacoco/org.jacoco.agent/ 0.5.6.201201232323/org.jacoco.agent-0.5.6.201201232323-runtime.jar=destfile=/path/to/target/jacoco.exec

By default, maven-surefire-plugin basically "prepends" this property (if it's set to anything) to its forked java test processes, so they get the goods. Ex: java ${argLine ends up here}> -jar /xxx/surefirebooter3741906822495182152.jar

Typically (without jacoco), if you want to also add something else of your own to that argLine (for instance, -Xmx1G or the like), you just set it in the surefire configuration, like

 <build>    <plugins>     <plugin>        <artifactId>maven-surefire-plugin</artifactId>          <configuration>             <argLine>-Xmx1G</argLine>           </configuration>      </plugin> 

However, if you're using jacoco, you can't do it the normal way you do it by setting a global property, this way instead (this is the pom's root global properties):

  <properties>     <argLine>-Xmx1G</argLine>   </properties> 

If you do set the <configuration><argLine> then it basically overrides the system property, so jacoco arguments aren't passed down to the child process. So that's why you use the property way instead. If you specify a property argLine then jacoco will just add its parameters to whatever you specify, then surefire will use it.

However, what if your parent pom has already set the plugin's <configuration><argLine> to something? Or if you yourself are setting it? It will basically use that value instead of the property that jacoco is setting (you've specified a manual override).

If you're specifying <configuration><argLine> yourself, you can change that argLine into a property (see above), and remove the <configuration><argLine> and it should work. If you can't control the parent, and the parent specifies something for argline, then you'll need to go the the <configuration><argLine>${argLine} -Xmx1G</argLine> route. This is to instruct it to ignore whatever the parent set this value to, and use argLine instead (the one jacoco sets for you). (It's unclear to me if there's an easy way to "add" to the value the parent pom has for this value, if anybody knows how feel free to comment here).

But what if jacoco doesn't run for some target, or some profile? Then the variable ${argLine} never gets set, and you can run into an error like this:

Execution default-test of goal org.apache.maven.plugins:maven-surefire-plugin:2.14:test failed: The forked VM terminated without saying properly goodbye. VM crash or System.exit called ? [ERROR] Command was/bin/sh -c cd ...java '${argLine}' ...

Well it turns out that jacoco only "adds" to the property named argLine, when it runs. So you can safely add a <properties><argLine></argLine></properties> to your pom (unless you already have that set in the parent pom, then you don't need to add anything). If jacoco is ever invoked, it adds to it. If not, it's set to an empty string, which is OK. It's also unclear if there's a way to "add" to the parent's value for a property, so it's either inherit it, if you know it exists, or specify it as empty.

So, in the end for me, since my upstream (inaccessible) parent pom declared it like

<configuration><argList>${argList}</argList></configuration>

I was forced to basically follow that route, since it was set already in an (out of my control) parent pom, thusly:

<configuration><argList>${argList} -Xmx1G</argList></configuration>

NB that Intellij will complain and "not add any settings" to your unit test if you have this in your pom:

<configuration><argLine>${argLine} -DcustomOption=X...</argLine>

but don't declare a property named argLine at all (even though it works on the command line mvn just fine). Fix/work around: declare an empty 'argLine' global property, and/or just move your -DcustomOption=X to the property declaration instead, see above. If you "only" set it in the property declaration then for IntelliJ to pick it up you'll also need <configuration><argLine>${argLine}</argLine>... :|

Unfortunately even this wasn't enough, it hosed sonar, though worked with IntelliJ + maven. Not sure why. Changed the way I parsed times instead, so didn't have to mess with the zones (i.e. "got them right" in the code).

like image 33
rogerdpack Avatar answered Sep 29 '22 20:09

rogerdpack