在maven中不能使用jacoco JVM参数和surefire JVM参数

我正在使用jacoco插件的maven生成代码覆盖率度量。 我在使用jacoco插件所需的java选项configurationsurefire插件时遇到一些困难。 我已经看到了堆栈溢出已经有一些答案,但有些不适合我。

我有一个多模块项目,我的一个模块configurationsurefire插件如下:

foo/pom.xml

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

这按预期工作。

现在我想包含jacoco来获取代码覆盖度量,所以我添加了一个CodeCoverageconfiguration文件来处理所有的jacococonfiguration:

parent/pom.xml

 <profile> <id>CodeCoverage</id> <build> <pluginManagement> <plugins> <plugin> <groupId>org.jacoco</groupId> <artifactId>jacoco-maven-plugin</artifactId> <executions> <execution> <id>jacoco-initialize</id> <goals><goal>prepare-agent</goal></goals> <configuration> <propertyName>surefire.argLine</propertyName> </configuration> ... </execution> <executions> </plugin> </plugins> </pluginManagement> </build> </profile> 

在这里可以看到,如果指定了CodeCoverageconfiguration文件,那么将jacoco插件configuration为使用surefire.argLine属性,并且该属性用于configurationargLine插件的argLine

然后,我更新了foo模块的pom.xml文件,以使用由jacoco插件生成的surefire.argLine属性:

foo/pom.xml

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

这个方法是在jacoco插件文档中指定的(参见[1])。

当我使用CodeCoverageconfiguration文件构buildfoo模块时,我看到以下内容:

 [foo] $ mvn clean install -X -PCodeCoverage ... [INFO] --- jacoco-maven-plugin:0.7.0.201403182114:prepare-agent (jacoco-initialize) @ foo --- [INFO] surefire.argLine set to -javaagent:...\\org.jacoco.agent\\0.7.0.201403182114\\org.jacoco.agent-0.7.0.201403182114-runtime.jar=destfile=...\foo\\\target\\coverage-reports\\jacoco-ut.exec ... [DEBUG] Configuring mojo 'org.apache.maven.plugins:maven-surefire-plugin:2.13:test' with basic configurator --> [DEBUG] (s) argLine = -javaagent:...\\org.jacoco.agent\\0.7.0.201403182114\\org.jacoco.agent-0.7.0.201403182114-runtime.jar=destfile=...\\foo\\target\\coverage-reports\\jacoco-ut.exec -XX:MaxPermSize=512m ... [INFO] --- jacoco-maven-plugin:0.7.0.201403182114:report (jacoco-site) @ foo --- [INFO] Analyzed bundle 'Foo' with 59 classes` 

因此, jacoco插件被执行,一个surefire.argLine属性被创build, argLine插件的argLine使用argLine属性和本地MaxPermSize参数,并生成一个target\code-coverage\jacoc-ut-exec文件,如预期。

但是,如果我不使用CodeCoverageconfiguration文件,那么我得到一个错误,因为${surefire.argLine}属性(在foo/pom.xml )不是由jacoco插件创build的,并且没有在任何地方定义:

 [foo] $ mvn clean install -X ... [DEBUG] Configuring mojo 'org.apache.maven.plugins:maven-surefire-plugin:2.13:test' with basic configurator --> [DEBUG] (s) argLine = ${surefire.argLine} -XX:MaxPermSize=512m ... Error: Could not find or load main class ${surefire.argLine}` 

没有调用jacoco插件的Sinec ,没有surefire.argLine属性创build,因此错误。

所以,我回到parent/pom.xml并创build这个属性,没有初始值:

parent/pom.xml

 <properties> <surefire.argLine></surefire.argLine> </properties> 

现在,当我不使用CodeCoverageconfiguration文件构buildfoo模块时,我不会遇到任何错误:

 [foo] $ mvn clean install -X ... [DEBUG] Configuring mojo 'org.apache.maven.plugins:maven-surefire-plugin:2.13:test' with basic configurator --> [DEBUG] (s) argLine = -XX:MaxPermSize=512m ... [INFO] BUILD SUCCESS` 

现在可以肯定的是 argline是正确的(使用空的surefire.argLine属性),没有target\code-coverage目录。

所以现在我回到使用CodeCoverageconfiguration文件生成代码指标:

 [foo] $ mvn clean install -X -PCodeCoverage ... [INFO] --- jacoco-maven-plugin:0.7.0.201403182114:prepare-agent (jacoco-initialize) @ foo --- [INFO] surefire.argLine set to -javaagent:...\\org.jacoco.agent\\0.7.0.201403182114\\org.jacoco.agent-0.7.0.201403182114-runtime.jar=destfile=...\\foo\\target\\coverage-reports\\jacoco-ut.exec ... [DEBUG] Configuring mojo 'org.apache.maven.plugins:maven-surefire-plugin:2.13:test' with basic configurator --> [DEBUG] (s) argLine = -XX:MaxPermSize=512m ... [INFO] --- jacoco-maven-plugin:0.7.0.201403182114:report (jacoco-site) @ foo --- [INFO] Skipping JaCoCo execution due to missing execution data file:...\foo\target\coverage-reports\jacoco-ut.exec 

在这里可以看到, jacoco插件被调用并设置了surefire.argLine属性,但是在parent/pom.xml文件中定义了具有空值的surefire.argLine属性实际上是用来为surefire插件创buildargline的。

因此,当我使用CodeCoverageconfiguration文件时,没有jacoco-ut.exec文件,也没有target\code-coverage目录。

我不知道我在这里做错了什么。 我按照jacoco文档的build议声明了一个argLine属性,并且当一个surefire插件需要指定附加参数时使用它。 堆栈溢出的其他答案build议创build一个与jacoco argLine属性相同的属性来处理未调用jacoco时的情况。

有什么build议么?

编辑

也许有一个解决scheme是显式声明CodeCoverageconfiguration文件中的surefire.argLine属性,而忘记使用jacoco插件的argLine

 <profile> <id>CodeCoverage</id> <properties> <surefire.argLine>-javaagent:${jacoco.agent.jar}=destfile=${jacoco.report.path}</surefire.argLine> </properties> <build> <plugins> <plugin> <groupId>org.jacoco</groupId> <artifactId>jacoco-maven-plugin</artifactId> <executions> <execution> <id>jacoco-initialize</id> <goals> <goal>prepare-agent</goal> </goals> <!-- no longer specifying 'argLine' for jacoco plugin ... --> </execution> <executions> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <configuration> <!-- ... instead the arg line is configured explicitly for surefire plugin. --> <argLine>${surefire.argLine}</argLine> </configuration> </plugin> </plugins> </plugin> </build> 

这将创buildsurefire.argLine属性来使用jacoco插件所需的java代理,并configurationsurefire插件将该属性用于其JVM参数。 jacoco插件现在将创build一个argLine属性,但是这将被忽略。 这不是一个优雅的解决scheme(因为我正在假设如何jacoco插件的工作,这可能会在未来的版本中改变)。

编辑

jacoco.agent.jar属性还必须通过指向它在本地存储库中的位置来设置(不知道这是否健壮),或者使用依赖插件将jacoco代理jar复制到本地构build目录:

 <profile> <id>CodeCoverage</id> <properties> <jacoco.agent.jar>${project.build.directory}/jacoco-agent.jar</jacoco.agent.jar> ... </project> <build> ... <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-dependency-plugin</artifactId> <executions> <execution> <id>download-jacoco-agent</id> <phase>process-test-resources</phase> <goals> <goal>copy</goal> </goals> <configuration> <artifactItems> <artifactItem> <groupId>org.jacoco</groupId> <artifactId>org.jacoco.agent</artifactId> <version>${jacoco.version}</version> <classifier>runtime</classifier> <outputDirectory>${project.build.directory}</outputDirectory> <destFileName>jacoco-agent.jar</destFileName> </artifactItem> </artifactItems> </configuration> </execution> </executions> </plugin> </plugins> </build> </profile> 

编辑

不知道是否使用依赖插件是正确的方法,或者指向本地存储库中的jacoco代理工件:

 <profile> <id>CodeCoverage</id> <properties> <jacoco.agent.jar>${settings.localRepository}/org/jacoco/org.jacoco.agent/${jacoco.version}/org.jacoco.agent-${jacoco.version}-runtime.jar</jacoco.agent.jar> </properties> ... </profile> 

这更简单,不需要将工件复制到本地构build目录,但是很脆弱:存储库布局中的更改将会破坏此工作。

[1] http://www.eclemma.org/jacoco/trunk/doc/prepare-agent-mojo.html

由于jacoco-maven-plugin:prepare-agent目标在maven-surefire-plugin之前执行,请尝试将${argLine}variables添加到由maven-surefire-plugin设置的argLine值中。

例:

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

我有同样的问题,这个解决scheme为我工作,没有任何需要重新configuration聚甲醛的其他部分。

尝试使用

 @{argLine} 

代替

 ${argLine} 

(或在你的情况下surefire.argLine

它允许surefire读取由其他插件修改的属性,而不是读取由Maven本身取代的属性。 然后你可以设置argLine参数在Maven属性中为空:

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

这现在不会造成任何问题。 更多这里: 我如何使用argLine中的其他插件设置的属性?

如果您的项目已经使用argLine来configurationsurefire-maven-plugin,请确保将argLine定义为属性,而不是插件configuration的一部分 。 例如:

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

生成的覆盖信息在执行过程中收集,默认情况下在过程终止时写入文件。

为我工作。 请参阅: http : //www.eclemma.org/jacoco/trunk/doc/prepare-agent-mojo.html

尝试在属性部分添加argLine属性(如下面的代码所示),而不是将其添加到maven-sure-fire插件的configuration部分。 Jacoco maven插件将只是附加到这一点,事情将按预期工作。

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

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

我最近遇到了同样的问题,甚至采取了相同的步骤,你所描述的相同的结果。 没有干净的解决scheme,我发现为我工作。

所以我在debugging模式下运行了几个步骤,似乎Mavenreplace了两次属性。 这不仅仅是一种懒惰的方式,正如我想的那样,而是以一种既急又懒的方式:

  1. 急切地 (在运行任何目标之前)被replace的静态属性(在POM的properties部分定义,也可能是settings.xml),
  2. 懒惰 (每次执行之前)被replace为dynamic属性。

这是我们将空白属性设置为默认值的步骤失败的地方。 Maven刚刚去了:

  1. 急于取代默认值(空白)
  2. JaCoCo设置dynamic价值
  3. 懒惰的replacedynamic值(现在没有什么要replace,已经使用了空值)

最后,解决scheme是dynamic设置默认值。 这可以用GMaven插件来完成,像这样:

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

所以现在Maven去:

  1. 渴望取代静态属性
  2. GMavendynamic设置默认值(如果configuration文件处于活动状态)
  3. JaCoCo设置dynamic价值
  4. Surefire以正确设置的argLine运行

使用活动configuration文件生成exec文件,使用非活动configuration文件时将使用空白默认值并生成成功。

我的解决scheme是使用多个configuration文件。

第一个configuration文件为surefire.argLinefailsafe.argLine设置一个空值,默认情况下处于活动状态。

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

第二个configuration文件具有jacoco插件configuration,默认情况下处于非活动状态。

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

当您激活声纳configuration文件时,声纳configuration文件将自动closures。

这应该比使用其他插件为你做这个工作更加优雅。 您现在可以在argLine中使用${surefire.argLine} surefire.argLine ${surefire.argLine}variables,并且在运行构build时它将始终存在并被设置。

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

如果你仍然有问题,因为$ {surefire.argLine}没有值,你也可以像这样设置一个虚拟属性:

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

我的解决scheme安全地在maven-surefire插件中使用argLine。

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

对于我从0.7.7.201606060606版本升级到0.7.9也解决了这个问题。

我不得不明确地将该版本添加到命令行(不仅仅是pom),因为构build服务器保持使用旧的版本。 这可以如下完成:

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

代替

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

jacoco插件网站(声纳)声明,argline必须作为一个属性添加。 对于我来说,在保证性插件设置中使用@{argLine}也是可行的。