【发布时间】:2014-06-05 02:05:54
【问题描述】:
我正在使用带有 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 使用surefire.argLine 属性和本地@ 987654336@ 参数,并按预期生成target\code-coverage\jacoc-ut-exec 文件。
但是,如果我不使用 CodeCoverage 配置文件,则会收到错误消息,因为 ${surefire.argLine} 属性(在 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}`
Sinec 没有调用 jacoco 插件,没有创建 surefire.argLine 属性,因此出现错误。
所以,我回到parent/pom.xml 并创建这个属性,没有初始值:
parent/pom.xml:
<properties>
<surefire.argLine></surefire.argLine>
</properties>
现在,当我在不使用 CodeCoverage 配置文件的情况下构建 foo 模块时,我没有收到任何错误:
[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 现在是正确的(使用空的surefire.argLine 属性)并且没有target\code-coverage 目录,正如预期的那样。
所以现在我回到生成代码指标,使用 CodeCoverage 配置文件:
[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属性,但是surefire.argLine属性在parent/pom.xml文件中定义的空值实际上是用来为 surefire 插件创建 argline。
因此,当我使用 CodeCoverage 配置文件时,没有jacoco-ut.exec 文件和target\code-coverage 目录。
我不确定我在这里做错了什么。我按照 jacoco 文档的建议声明了一个 argLine 属性,并在 surefire 插件需要指定其他参数时使用它。 Stack Overflow 上的其他答案建议创建一个与 jacoco argLine 属性同名的属性,以处理未调用 jacoco 的情况。
有什么建议吗?
编辑
也许一种解决方案是在 CodeCoverage 配置文件中显式声明 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>
这将创建 surefire.argLine 属性以使用 jacoco 插件所需的 java 代理,并配置 surefire 插件以使用该属性为其 JVM 参数。 jacoco 插件现在将创建一个 argLine 属性,但这将被忽略。这不是一个优雅的解决方案(因为我正在对 jacoco 插件的工作方式做出假设,这可能会在未来的版本中改变)。
编辑
jacoco.agent.jar 属性也必须设置,通过指向其在本地存储库中的位置(不确定这是否可靠)或使用 dependency 插件复制 jacoco 代理 jar 到本地构建目录:
<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>
编辑
不确定使用 dependency 插件是否是正确的方法,或者指向本地存储库中的 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>
这更简单,不需要将工件复制到本地构建目录,但很脆弱:存储库布局的更改会破坏这一点。
[1]http://www.eclemma.org/jacoco/trunk/doc/prepare-agent-mojo.html
【问题讨论】:
标签: maven jacoco maven-surefire-plugin