我使用了带有 Jacoco插件的 maven 来生成代码覆盖度量。我在使用 Jacoco插件所需的 java 选项配置 当然插件时遇到了一些困难。我已经在 Stack Overflow 上看到了一些关于这个问题的答案,但是有些东西对我不起作用。
我有一个多模块的项目,我的一个模块配置的 当然插件如下:
返回文章页面
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<argLine>-XX:MaxPermSize=512m</argLine>
</configuration>
</plugin>
</plugins>
一切如我所料。
现在我想合并 jacoco 来获得代码覆盖度量,所以我添加了一个 代码覆盖率配置文件来处理所有的 jacoco 配置:
返回文章页面
<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>
这里可以看到,如果指定了 代码覆盖率配置文件,那么 Jacoco插件就被配置为使用 surefire.argLine
属性,并且该属性用于为 当然插件配置 argLine
。
然后,我更新了 福模块的 Pom.xml文件,使用 Jacoco插件生成的 surefire.argLine
属性:
返回文章页面
<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])。
当我使用 代码覆盖率配置文件构建 福模块时,我看到以下内容:
[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
属性,当然插件的 argLine
使用 surefire.argLine
属性和本地 MaxPermSize
参数,然后像预期的那样生成一个 target\code-coverage\jacoc-ut-exec
文件。
但是,如果我没有使用 代码覆盖率配置文件,那么我会得到一个错误,因为 ${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}`
因为没有调用 Jacoco插件,所以没有创建 surefire.argLine
属性,所以出现了错误。
因此,我返回到 parent/pom.xml
并创建这个属性,它没有初始值:
返回文章页面
<properties>
<surefire.argLine></surefire.argLine>
</properties>
现在,当我在没有使用 代码覆盖率概要文件的情况下构建 福模块时,我不会得到任何错误:
[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
目录,正如预期的那样。
因此,现在我回过头来使用 代码覆盖率概要文件生成代码度量:
[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
属性实际上被用来为 当然插件创建 argline。
因此,在使用 代码覆盖率配置文件时,不存在 jacoco-ut.exec
文件和 target\code-coverage
目录。
我不知道我哪里做错了。我正在按照 Jacoco文档的建议声明一个 argLine
属性,并在 当然插件需要指定附加参数时使用它。关于 Stack Overflow 的其他答案建议创建一个与 Jacoco argLine 属性同名的属性,以便在未调用 Jacoco时处理这种情况。
有什么建议吗?
编辑
也许一种解决方案是在 代码覆盖率配置文件中显式声明 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>
这将创建使用 Jacoco插件所需的 java 代理的 当然可以 argLine属性,并将 当然插件配置为将该属性用于其 JVM 参数。Jacoco插件现在将创建一个 ArgLine属性,但这将被忽略。这不是一个优雅的解决方案(因为我对 Jacoco插件的工作方式做了一些假设,这可能会在将来的版本中改变)。
编辑
还必须通过指向其在本地存储库中的位置(不确定这是否健壮)或使用 依赖性插件将 Jacoco代理 jar 复制到本地构建目录来设置 jacoco.agent.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>
编辑
不确定使用 依赖性插件是否是正确的方法,或者指向本地存储库中的 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