不能在maven中使用jacoco JVM args和surefire JVM args

时间:2014-04-21 02:54:14

标签: maven jacoco maven-surefire-plugin

我正在使用带有 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

10 个答案:

答案 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两次替换属性。正如我想的那样,这不只是一种懒惰的方式,而是以热切和懒惰的方式:

  1. 急切地(在任何目标运行之前)被替换为静态属性(在POM的properties部分中定义,也可能是settings.xml),
  2. 懒洋洋地(在每次执行之前)被替换为动态属性。
  3. 这是我们将空白属性设置为默认值的步骤失败。 Maven刚刚去了:

    1. 急切替换默认值(空白)
    2. JaCoCo设置动态值
    3. 懒惰替换动态值(现在无需替换,已使用空白值)
    4. 最后解决方案是动态设置默认值。这可以使用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. GMaven动态设置默认值(如果配置文件处于活动状态)
      3. JaCoCo设置动态值
      4. Surefire使用正确设置的argLine
      5. 运行

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

答案 5 :(得分:4)

我的解决方案是使用多个配置文件。

第一个配置文件为surefire.argLinefailsafe.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个具有以下功能的域类:

    使用插件Surefire和Failsafe
  • 单元或集成测试
  • 了findBUGs。
  • 通过 Jacoco 测试覆盖率。

我让项目尽可能简单。该项目在示例项目中将这些和其他帖子的许多建议放在一起。谢谢你,贡献者!

自述文件给出了简要说明。它解释了如何使用 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:报告