我正在使用带有 jacoco 插件的maven来生成代码覆盖率指标。我在使用 jacoco 插件所需的java选项配置 surefire 插件时遇到了一些困难。我已经在Stack Overflow上看到了一些关于此问题的答案,但有些东西对我不起作用。
我有一个多模块项目,我的一个模块配置 surefire 插件,如下所示:
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来获取代码覆盖率指标,所以我添加了一个处理所有jacoco配置的 CodeCoverage 配置文件:
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>
这里可以看到,如果指定了 CodeCoverage 配置文件,那么 jacoco 插件配置为使用surefire.argLine
属性,并使用该属性为 surefire 插件配置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])。
当我使用 CodeCoverage 配置文件构建 foo 模块时,我看到以下内容:
[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
属性, surefire 插件的argLine
使用{{1} } property和本地surefire.argLine
参数,并按预期生成MaxPermSize
文件。
但是,如果我不使用 CodeCoverage 配置文件,那么我会收到错误,因为target\code-coverage\jacoc-ut-exec
属性(在${surefire.argLine}
中使用)不是由< em> jacoco 插件,并未在任何地方定义:
foo/pom.xml
未调用 jacoco 插件,没有创建[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}`
属性,因此出错。
所以,我回到surefire.argLine
并创建此属性,没有初始值:
parent/pom.xml
:
parent/pom.xml
现在,当我在不使用 CodeCoverage 配置文件的情况下构建 foo 模块时,我没有收到任何错误:
<properties>
<surefire.argLine></surefire.argLine>
</properties>
surefire argline现在正确(使用空的[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`
属性)并且没有surefire.argLine
目录,正如预期的那样。
现在我回到使用 CodeCoverage 配置文件生成代码指标:
target\code-coverage
可以在这里观察到 jacoco 插件被调用并设置[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
属性,但surefire.argLine
属性在{{1}中定义了空值} file实际上用于为 surefire 插件创建argline。
因此,当我使用 CodeCoverage 配置文件时,没有surefire.argLine
文件,也没有parent/pom.xml
目录。
我不确定我在这里做错了什么。我按照 jacoco 文档的建议声明了jacoco-ut.exec
属性,并在 surefire 插件需要指定其他参数时使用它。 Stack Overflow上的其他答案建议创建一个与 jacoco argLine属性同名的属性,以处理未调用 jacoco 时的情况。
有什么建议吗?
修改
也许一个解决方案是在 CodeCoverage 配置文件中显式声明target\code-coverage
属性,而忘记使用 jacoco 插件的argLine
:
surefire.argLine
这将创建 surefire.argLine 属性以使用 jacoco 插件所需的java代理,并配置 surefire 插件以供使用它的JVM args的那个属性。 jacoco 插件现在将创建 argLine 属性,但这将被忽略。它不是一个优雅的解决方案(因为我对 jacoco 插件的工作方式做出了假设,这可能会在将来的版本中发生变化)。
修改
还必须设置argLine
属性,方法是指向它在本地存储库中的位置(不确定这是否健壮),还是使用依赖插件来复制 jacoco 代理jar到本地构建目录:
<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>
修改
不确定使用依赖插件是正确的方法,还是指向本地存储库中的jacoco代理工件:
jacoco.agent.jar
这更简单,并且不需要将工件复制到本地构建目录,但是很脆弱:存储库布局中的更改将破坏此。
[1] http://www.eclemma.org/jacoco/trunk/doc/prepare-agent-mojo.html
答案 0 :(得分:33)
由于jacoco-maven-plugin:prepare-agent
目标在maven-surefire-plugin之前执行,请尝试将${argLine}
变量添加到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>
我遇到了同样的问题,这个解决方案对我有用,无需重新配置POM的其他部分。
答案 1 :(得分:32)
尝试使用
@{argLine}
而不是
${argLine}
(或您的情况为surefire.argLine
)
它允许surefire读取由其他插件修改的属性,而不是读取由Maven本身替换的属性。然后,您可以在Maven属性中将argLine
参数设置为空:
<properties>
<argLine></argLine>
</properties>
现在不会造成任何问题。更多信息:How do I use properties set by other plugins in argLine?
答案 2 :(得分:14)
如果您的项目已使用argLine配置surefire-maven-plugin,请确保将argLine定义为属性,而不是作为插件配置的一部分。例如:
<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
答案 3 :(得分:11)
尝试在属性部分添加argLine属性(如下面的代码所示),而不是在maven-sure-fire插件的配置部分中添加它。 Jacoco maven插件只会附加到此,事情将按预期工作。
<properties>
<argLine>-XX:MaxPermSize=512m</argLine>
</properties>
请参阅https://docs.sonarqube.org/display/PLUG/Usage+of+JaCoCo+with+Java+Plugin
答案 4 :(得分:4)
我最近遇到了同样的问题,甚至隐含地采用了与您描述的相同的步骤。我找不到干净的解决方案。
所以我在调试模式下运行了几个步骤,似乎Maven两次替换属性。正如我想的那样,这不只是一种懒惰的方式,而是以热切和懒惰的方式:
properties
部分中定义,也可能是settings.xml),这是我们将空白属性设置为默认值的步骤失败。 Maven刚刚去了:
最后解决方案是动态设置默认值。这可以使用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说:
使用活动配置文件生成exec文件,使用非活动配置文件时,将使用空白默认值并构建成功。
答案 5 :(得分:4)
我的解决方案是使用多个配置文件。
第一个配置文件为surefire.argLine
和failsafe.argLine
设置了空白值,默认情况下处于活动状态。
<profile>
<id>not-sonar</id>
<properties>
<surefire.argLine/>
<failsafe.argLine/>
</properties>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
</profile>
第二个配置文件具有jacoco插件配置,默认情况下处于非活动状态。
<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>
当您激活声纳配置文件时,非声纳配置文件将自动关闭。
这应该比使用其他插件为您完成工作更优雅。您现在可以在argLine中使用${surefire.argLine}
变量,它将始终存在并在您运行构建时设置。
<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>
答案 6 :(得分:2)
我的解决方案是在maven-surefire-plugin中安全地使用argLine。
{{1}}
答案 7 :(得分:1)
对于我来说,将版本从0.7.7.201606060606升级到0.7.9也修复了这个问题。
我必须明确地将版本添加到命令行(而不仅仅是pom),因为构建服务器保持使用旧版本。这可以按如下方式完成:
org.jacoco:jacoco-maven-plugin:0.7.9:prepare-agent
而不是
org.jacoco:jacoco-maven-plugin:prepare-agent
jacoco plugin site (for sonar)表示必须将argline添加为属性。对我来说,在surefire插件设置中使用@{argLine}
时也能正常工作。
答案 8 :(得分:1)
我添加了一个Maven/Java project,其中包含1个具有以下功能的域类:
我让项目尽可能简单。该项目在示例项目中将这些和其他帖子的许多建议放在一起。谢谢你,贡献者!
自述文件给出了简要说明。它解释了如何使用 Jacoco 运行用户或集成测试。
享受!
答案 9 :(得分:1)
将POM.xml更新为
<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>
然后最重要的是运行具有目标的Maven项目: MVN JACOCO:准备剂清洁测试JACOCO:报告