Cannot use jacoco JVM args and surefire JVM args together in maven

为君一笑 提交于 2019-11-27 11:45:36
Will Gage

Since the jacoco-maven-plugin:prepare-agent goal executes before the maven-surefire-plugin, try adding the ${argLine} variable into the argLine value set by the maven-surefire-plugin.

Example:

<plugin>
  <artifactId>maven-surefire-plugin</artifactId>
  <version>2.12.1</version>
  <configuration>
    <argLine>-server -ea -XX:MaxPermSize=256m -Xmx4g -XX:-UseSplitVerifier ${argLine}</argLine>
  </configuration>
</plugin>

I had the same problem and this solution worked for me, without any need to reconfigure other sections of the POM.

Kaszaq

Try using

@{argLine}

instead of

${argLine}

(or surefire.argLine in your case)

It allows surefire to read a property as modified by other plugins instead of reading the one substituted by Maven itself. Then you can set the argLine param to empty in Maven properties:

<properties>
    <argLine></argLine>
</properties>

Which now will not cause any problems. More here: How do I use properties set by other plugins in argLine?

If your project already uses the argLine to configure the surefire-maven-plugin, be sure that argLine defined as a property, rather than as part of the plugin configuration. For example:

  <properties>
    <argLine>-your -extra -arguments</argLine>
  </properties>
  ...
  <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <configuration>
      <!-- Do not define argLine here! -->
    </configuration>
  </plugin>

Resulting coverage information is collected during execution and by default written to a file when the process terminates.

Worked for me. See: http://www.eclemma.org/jacoco/trunk/doc/prepare-agent-mojo.html

Faisal Feroz

Try adding the argLine property in the properties section (as shown in the code below) instead of adding it in the configuration section of maven-sure-fire plugin. Jacoco maven plugin will just append to this and things will work as expected.

<properties>
  <argLine>-XX:MaxPermSize=512m</argLine>
</properties>

See https://docs.sonarqube.org/display/PLUG/Usage+of+JaCoCo+with+Java+Plugin

I recently ran into the same issue and even took implicitly the same steps as you described with the same result. No clean solution I found worked for me.

So I ran several steps in debug mode and it seems that Maven replaces properties twice. That is not just in a lazy manner, as I thought, but in both eager and lazy manner:

  1. eagerly (before any goal is run) are replaced static properties (defined in properties section of POM and probably also settings.xml),
  2. lazily (before each execution) are replaced dynamic properties.

This is where our step with setting a blank property as a default failed. Maven just went:

  1. eager replace of default value (blank)
  2. JaCoCo sets dynamic value
  3. lazy replace of dynamic values (nothing to replace now, already used the blank value)

Finally the solution is to set the default value dynamically. This can be done with GMaven plugin like this:

<plugin>
  <groupId>org.codehaus.gmaven</groupId>
  <artifactId>gmaven-plugin</artifactId>
  <version>1.5</version>
  <executions>
    <execution>
      <id>set-default-values</id>
      <phase>initialize</phase>
      <goals>
        <goal>execute</goal>
      </goals>
      <configuration>
        <source>
          project.properties.'surefire.argLine' = ''
        </source>
      </configuration>
    </execution>
  </executions>
</plugin>

So now Maven goes:

  1. eager replace of static properties
  2. GMaven dynamically sets default value (if profile is active)
  3. JaCoCo sets dynamic value
  4. Surefire runs with correctly set argLine

With active profile the exec file is generated, with non-active profile the blank default value is used and build succeeds.

My solution is to use multiple profiles.

The first profile sets a blank value for the surefire.argLine and the failsafe.argLine and is active by default.

<profile>
    <id>not-sonar</id>
    <properties>
        <surefire.argLine/>
        <failsafe.argLine/>
    </properties>
    <activation>
        <activeByDefault>true</activeByDefault>
    </activation>
</profile>

The second profile has the jacoco plugin configuration and is inactive by default.

<profile>
<id>sonar</id>
<activation>
    <activeByDefault>false</activeByDefault>
</activation>
<build>
    <plugins>
        <plugin>
            <groupId>org.jacoco</groupId>
            <artifactId>jacoco-maven-plugin</artifactId>
            <version>${jacoco-maven-plugin-version}</version>
            <executions>
                <execution>
                    <id>default-prepare-agent</id>
                    <goals>
                        <goal>prepare-agent</goal>
                    </goals>
                    <configuration>
                        <propertyName>surefire.argLine</propertyName>
                    </configuration>
                </execution>
                <execution>
                    <id>default-prepare-agent-integration</id>
                    <goals>
                        <goal>prepare-agent-integration</goal>
                    </goals>
                    <configuration>
                        <propertyName>failsafe.argLine</propertyName>
                    </configuration>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>
</profile>

When you activate the sonar profile the not-sonar profile will automatically be turned off.

This should be a little more elegant than using other plugins to do the work for you. You can now use the ${surefire.argLine} variable in your argLine and it will always exists and be set when you run your build.

  <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <configuration>
      <argLine>${surefire.argLine} -XX:MaxPermSize=512m</argLine>
    </configuration>
  </plugin>

If you still have problems because the ${surefire.argLine} does not have a value you can also set a dummy property like so:

<profile>
    <id>not-sonar</id>
    <properties>
        <surefire.argLine>-DdummyProperty=notUsed</surefire.argLine>
        <failsafe.argLine>-DdummyProperty=notUsed</failsafe.argLine>
    </properties>
    <activation>
        <activeByDefault>true</activeByDefault>
    </activation>
</profile>

My solution to use argLine in the maven-surefire-plugin safely.

<plugin>
    <groupId>org.codehaus.groovy.maven</groupId>
    <artifactId>gmaven-plugin</artifactId>
    <version>2.0</version>
    <executions>
        <execution>
            <id>set-custom-arg-line</id>
            <phase>validate</phase>
            <goals>
                <goal>execute</goal>
            </goals>
            <configuration>
                <source>
                    def argLine = project.properties['argLine'];
                    if (argLine == null) {
                        argLine = "";
                    }
                    project.properties.argLine = argLine;
                </source>
            </configuration>
        </execution>
    </executions>
</plugin>

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>2.19.1</version>
    <configuration>
        <argLine>-Xmx1024m ${argLine}</argLine>
    </configuration>
</plugin>

For me upgrading the version from 0.7.7.201606060606 to 0.7.9 also fixed this.

I had to explicitly add the version to the commandline (not just to the pom) because the build server kept using the old verison. This can be done as follows:

 org.jacoco:jacoco-maven-plugin:0.7.9:prepare-agent

instead of

org.jacoco:jacoco-maven-plugin:prepare-agent

The jacoco plugin site (for sonar) states that argline must be added as a property. For me it also worken when using the @{argLine} in the surefire plugin settings.

Update the POM.xml as

<plugin>
    <groupId>org.jacoco</groupId>
    <artifactId>jacoco-maven-plugin</artifactId>
    <version>0.7.7.201606060606</version>
    <executions>
      <execution>
        <goals>
            <goal>prepare-agent</goal>
        </goals>
      </execution>
      <execution>
            <id>report</id>
            <phase>prepare-package</phase>
            <goals>
              <goal>report</goal>
            </goals>
      </execution>
    </executions>
</plugin>

<plugin>
      <artifactId>maven-surefire-plugin</artifactId>
      <version>2.12.1</version>
      <configuration>
         <argLine>${argLine} -XX:PermSize=256m -XX:MaxPermSize=1048m</argLine> 
      </configuration>
</plugin>

and then the most important thing is to run the Maven project with goals: mvn jacoco:prepare-agent clean test jacoco:report

I have added a Maven/Java project with 1 domain class with the following features:

  • Unit or Integration testing with the plugins Surefire and Failsafe.
  • Findbugs.
  • Test coverage via Jacoco.

I kept the project as simple as possible. The project puts many suggestions from these and other posts together in an example project. Thank you, contributors!

The readme file gives a brief explanation. It explains how you can run either a user or an integration test with Jacoco.

Enjoy!

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!