Ошибка плагина Maven JaCoCo

Я настроил плагин Maven JaCoCo следующим образом в моем файле pom.xml:

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <jacoco.version>0.5.9.201207300726</jacoco.version>
</properties>

<profiles>
    <profile>
        <id>jacoco4</id>
        <build>
            <plugins>
                <plugin>
                    <groupId>org.jacoco</groupId>
                    <artifactId>jacoco-maven-plugin</artifactId>
                    <version>${jacoco.version}</version>
                    <executions>
                        <execution>
                            <goals>
                                <goal>prepare-agent</goal>
                            </goals>
                            <configuration
                            <destfile>${project.build.directory}/target/jacoco.exec</destfile>
                            <datafile>${project.build.directory}/target/jacoco.exec</datafile>
                                <output>file</output>
                                <append>true</append>
                            </configuration>
                        </execution>
                        <execution>
                            <id>report</id>
                            <phase>prepare-package</phase>
                            <goals>
                                <goal>report</goal>
                            </goals>
                        </execution>
                    </executions>
                </plugin>
            </plugins>
        </build>
    </profile>
</profiles>

Я использую Windows 7 и плагин apache-maven-3.0.4. Когда я набираю mvn -P jacoco4 install, либо с терминала cygwin, либо с терминала командной строки, Maven загружает и запускает плагин JaCoCo, но тогда файл jacoco.exec, похоже, не был создан. Ниже приведено сообщение об ошибке:

[ERROR] Unable to read execution data file C:\Users\brownru\workspace64new\vps9\vps-fileserver\target\jacoco.exec: C:\Users\brownru\workspace64new\vps9\vps-fileserver\target\jacoco.exec (The system cannot find the file specified)
java.io.FileNotFoundException: C:\Users\brownru\workspace64new\vps9\vps-fileserver\target\jacoco.exec (The system cannot find the file specified)
        at java.io.FileInputStream.open(Native Method)
        at java.io.FileInputStream.<init>(FileInputStream.java:120)
        at org.jacoco.maven.ReportMojo.loadExecutionData(ReportMojo.java:251)
        at org.jacoco.maven.ReportMojo.executeReport(ReportMojo.java:228)
        at org.jacoco.maven.ReportMojo.execute(ReportMojo.java:217)
        at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:101)
        at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:209)
        at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:153)
        at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:145)
        at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:84)
        at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:59)
        at org.apache.maven.lifecycle.internal.LifecycleStarter.singleThreadedBuild(LifecycleStarter.java:183)
        at org.apache.maven.lifecycle.internal.LifecycleStarter.execute(LifecycleStarter.java:161)
        at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:320)
        at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:156)
        at org.apache.maven.cli.MavenCli.execute(MavenCli.java:537)
        at org.apache.maven.cli.MavenCli.doMain(MavenCli.java:196)
        at org.apache.maven.cli.MavenCli.main(MavenCli.java:141)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced(Launcher.java:290)
        at org.codehaus.plexus.classworlds.launcher.Launcher.launch(Launcher.java:230)
        at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode(Launcher.java:409)
        at org.codehaus.plexus.classworlds.launcher.Launcher.main(Launcher.java:352)

Появится это сообщение об ошибке, включив в конфигурацию плагина теги destfile и datafile:

<destfile>${project.build.directory}/target/jacoco.exec</destfile>
<datafile>${project.build.directory}/target/jacoco.exec</datafile>

Может кто-нибудь, пожалуйста, скажите мне, что я делаю неправильно?

Ответ 1

У меня были те же проблемы с jacoco и maven. Это было связано с родительским pom, перезаписывающим конфигурацию surefire. В этом случае этот плагин не использовал аргумент (для аргумента jvm), определяющий агент.

Решение заключалось в том, чтобы вернуть элемент конфигурации "argLine"

<plugin>
  <artifactId>maven-surefire-plugin</artifactId>
  <configuration>
   <argLine>${argLine}</argLine>
  </configuration>
 </plugin>

Полный плагин conf выглядит как

<plugin>
  <artifactId>maven-surefire-plugin</artifactId>
  <configuration>
    <skip>true</skip>
  </configuration>
  <executions>
    <execution>
      <id>unit-test</id>
      <phase>test</phase>
      <goals>
        <goal>test</goal>
      </goals>
      <configuration>
        <skip>${maven.test.skip}</skip>
        <argLine>${argLine}</argLine>
        <excludes>
          <exclude>**/*IntegrationTest.java</exclude>
        </excludes>
      </configuration>
    </execution>
    <execution>
      <id>integration-test</id>
      <phase>integration-test</phase>
      <goals>
        <goal>test</goal>
      </goals>
      <configuration>
        <skip>${skipITs}</skip>
        <argLine>${argLine}</argLine>
        <includes>
          <include>**/*IntegrationTest.java</include>
        </includes>
      </configuration>
    </execution>
  </executions>
</plugin>
<plugin>
    <groupId>org.jacoco</groupId>
    <artifactId>jacoco-maven-plugin</artifactId>
    <version>0.5.10.201208310627</version>
    <configuration>
        <skip>${maven.test.skip}</skip>
        <destFile>${basedir}/target/coverage-reports/jacoco-unit.exec</destFile>
        <dataFile>${basedir}/target/coverage-reports/jacoco-unit.exec</dataFile>
        <output>file</output>
        <append>true</append>
    </configuration>
    <executions>
        <execution>
            <id>jacoco-initialize</id>
            <goals>
                <goal>prepare-agent</goal>
            </goals>
        </execution>
        <execution>
            <id>jacoco-site</id>
            <phase>verify</phase>
            <goals>
                <goal>report</goal>
            </goals>
        </execution>
    </executions>
</plugin>

Надеюсь, что это будет полезно

Ответ 2

ОК, я думаю, я понял, что происходит.

По умолчанию плагин jacoco "запускается" перед фазой тестирования (как правило, он запускает цель prepare-agent на этапе инициализации жизненного цикла), а когда он запускается, он просто устанавливает свойство maven с именем "argLine" в нечто вроде -javaagent=jacoco.jar

например:

[INFO] argLine установлен в -javaagent: /username/.m2/repository/org/jacoco/org.jacoco.agent/0.5.6.201201232323/org.jacoco.agent-0.5.6.201201232323-runtime.jar = destfile =/путь/to/target/jacoco.exec

По умолчанию maven-surefire-plugin в основном "добавляет" это свойство (если оно установлено в какое-либо значение) к его разветвленным процессам тестирования Java, поэтому они получают товары. Пример: java ${argLine ends up here}> -jar/xxx/surefirebooter3741906822495182152.jar

Как правило (без jacoco), если вы хотите добавить что-то еще в argLine (например, -Xmx1G или подобное), вы просто устанавливаете его в безошибочной конфигурации, например

 <build>
   <plugins>
    <plugin>
       <artifactId>maven-surefire-plugin</artifactId>
         <configuration>
            <argLine>-Xmx1G</argLine>
          </configuration>
     </plugin>

Однако, если вы используете jacoco, вы не можете сделать это обычным способом вы это сделать, установив глобальное свойство, таким образом, вместо того, чтобы (это корень ПОМ глобальные свойства):

  <properties>
    <argLine>-Xmx1G</argLine>
  </properties>

Если вы установите <configuration><argLine> тогда он в основном переопределяет системное свойство, поэтому аргументы jacoco не передаются дочернему процессу. Так вот почему вместо этого вы используете свойство. Если вы укажете свойство argLine то jacoco просто добавит его параметры к тому, что вы укажете, а затем его обязательно использует.

Однако, что если ваш родительский pom уже установил плагин <configuration><argLine> на что-то? Или если вы сами это настраиваете? Он будет в основном использовать это значение вместо свойства, которое устанавливает jacoco (вы указали ручное переопределение).

Если вы сами задаете <configuration><argLine>, вы можете изменить этот argLine на свойство (см. Выше) и удалить <configuration><argLine> и он должен работать. Если вы не можете контролировать родительский объект, и родительский объект указывает что-то для argline, то вам нужно пойти по маршруту <configuration><argLine>${argLine} -Xmx1G</argLine>. Это сделано для того, чтобы он игнорировал любой родительский объект, для которого установлено это значение, и использовал вместо него argLine (тот, который jacoco устанавливает для вас). (Для меня неясно, есть ли простой способ "добавить" значение, которое родительский pom имеет для этого значения, если кто-нибудь знает, как не стесняйтесь комментировать здесь).

Но что, если jacoco не работает для какой-либо цели или профиля? Тогда переменная ${argLine} никогда не будет установлена, и вы можете столкнуться с такой ошибкой:

Выполнение проверки по умолчанию цели org.apache.maven.plugins: maven-surefire-plugin: 2.14: проверка завершилась неудачно: разветвленная виртуальная машина завершилась, не сказав должного прощания. Виртуальный сбой или System.exit называется? [ОШИБКА] Команда была /bin/sh -c cd... java '$ {argLine}'...

Что ж, получается, что jacoco только "добавляет" свойство argLine при запуске. Таким образом, вы можете безопасно добавить <properties><argLine></argLine></properties> в ваш pom (если у вас уже нет этого набора в родительском pom, вам не нужно ничего добавлять). Если jacoco когда-либо вызывается, он добавляет к нему. Если нет, то устанавливается пустая строка, что нормально. Также неясно, есть ли способ "добавить" родительское значение для свойства, поэтому оно либо наследует его, если вы знаете, что оно существует, либо указываете его как пустое.

Итак, в конце концов для меня, так как мой родительский pom (недоступный) родитель объявил это как

<configuration><argList>${argList}</argList></configuration>

Я был вынужден в основном следовать по этому маршруту, так как он был установлен уже в (вне моего контроля) родительского pom, таким образом:

<configuration><argList>${argList} -Xmx1G</argList></configuration>

Обратите внимание, что Intellij будет жаловаться и "не добавлять никаких настроек" в ваш unit тест, если у вас есть это в вашей поме:

<configuration><argLine>${argLine} -DcustomOption=X...</argLine>

но вообще не объявляйте свойство с именем argLine (даже если оно прекрасно работает в командной строке mvn). Исправить/обойти: объявить пустое глобальное свойство 'argLine' и/или просто вместо этого переместить ваш -DcustomOption=X в объявление свойства, см. Выше. Если вы "только" установили его в объявлении свойства, то для того, чтобы IntelliJ поднял его, вам также понадобится <configuration><argLine>${argLine}</argLine>...: |

Ответ 3

Я также столкнулся с этой проблемой: JaCoCo не выводит выходной файл 'jacoco.exec', что означает, что анализ покрытия кода не происходит.

В моем случае это было также связано с использованием пользовательской argLine в плагине Maven Surefire, которая переопределила плагин JaCoCo Maven PlugLine, в результате чего JaCoCo не выполнялся.

Чтобы исправить это, я использовал необязательный параметр JaCoCo "propertyName", чтобы экспортировать его argLine в свойство Maven и включил его в строку аргумента Surefire:

<plugin>
    <groupId>org.jacoco</groupId>
    <artifactId>jacoco-maven-plugin</artifactId>
    <configuration>
        <propertyName>jacoco.agent.argLine</propertyName>
    </configuration>
    ...             
</plugin>

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>2.10</version>
    <configuration>
        <argLine>-XX:-UseSplitVerifier ${jacoco.agent.argLine}</argLine>
    </configuration>
</plugin>

Однако это вызвало проблему, когда отдельные тесты выполнялись в Netbeans. Поскольку плагин JaCoCo не был выполнен в этом сценарии, переменная "jacoco.agent.argLine" не была инициализирована, и Surefire не удалось выполнить какие-либо тесты.

Добавление пустого свойства "jacoco.agent.argLine" в pom решило проблему при запуске одиночных тестов, но это также остановило JaCoCo на экспорте своей argLine при ее выполнении, эффективно отключив JaCoCo.

Последняя часть решения, которое я использовал, это добавить профиль, который создает пустое свойство, и активируется только при задании одного теста:

<profiles>
    <profile>
        <activation>                
            <property>
                <name>test</name>      
            </property>
        </activation>
        <properties>
            <jacoco.agent.argLine></jacoco.agent.argLine>
        </properties>
    </profile>
</profiles>

Ответ 4

Я использую конфигурацию:

    <plugin>
        <groupId>org.jacoco</groupId>
        <artifactId>jacoco-maven-plugin</artifactId>
        <version>${jacoco.version}</version>
            <configuration>
                    <skip>${skipTests}</skip>
            </configuration>
            <executions>
                    <execution>
                                <id>jacoco-initialize</id>
                                <phase>initialize</phase>
                                <goals>
                                    <goal>prepare-agent</goal>
                                </goals>
                            </execution>
                            <execution>
                                <id>jacoco-site</id>
                                <phase>package</phase>
                                <goals>
                                    <goal>report</goal>
                                </goals>
                            </execution>
            </executions>
        </plugin>

Update: Конфигурация, создаваемая сонаром (sonar-pom.xml):

<plugin>
        <artifactId>maven-surefire-plugin</artifactId>
        <version>2.12</version>
        <executions>
          <execution>
            <id>default-test</id>
            <phase>test</phase>
            <goals>
              <goal>test</goal>
            </goals>
            <configuration>
              <excludedGroups>server,ignore,integration</excludedGroups>
            </configuration>
          </execution>
        </executions>
        <configuration>
          <excludedGroups>server,ignore,integration</excludedGroups>
          <argLine>-javaagent:/tmp/jacocoagent3671192291664069011.jar=destfile=target/jacoco.exec,excludes=*_javassist_*</argLine>
          <testFailureIgnore>true</testFailureIgnore>
        </configuration>
      </plugin>

Одна проблема - как определить "jacocoagent3671192291664069011.jar" для каждой сборки. Он должен быть в:

$M2_HOME/repository/org/jacoco/org.jacoco.agent/${jacoco.version}/org.jacoco.agent-${jacoco.version}-runtime.jar