Не удается использовать jacoco JVM args и surefire JVM args вместе в maven
я использую maven с jacoco плагин для генерации метрик покрытия кода. У меня возникли некоторые трудности в настройке верный плагин с параметрами java, требуемыми jacoco плагин. Я видел некоторые ответы об этом уже на переполнении стека, но что-то не работает для меня.
у меня есть многомодульный проект, и один из моих модулей настраивает верный плагин как следует:
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, чтобы получить метрики покрытия кода, поэтому я добавил CodeCoverage профиль, который обрабатывает всю конфигурацию jacoco:
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
собственность, а это свойство используется для настройки argLine
на верный плагин.
затем я обновил пом.в XML на фу модуль для использования surefire.argLine
свойство, генерируемое jacoco плагин:
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]).
когда я строю фу модуль с the 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.7.0.201403182114org.jacoco.agent-0.7.0.201403182114-runtime.jar=destfile=...foo\targetcoverage-reportsjacoco-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.7.0.201403182114org.jacoco.agent-0.7.0.201403182114-runtime.jar=destfile=...footargetcoverage-reportsjacoco-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 плагин выполнен, a surefire.argLine
свойства, в argLine
на верный плагин использует surefire.argLine
недвижимость и местные и targetcode-coveragejacoc-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}`
Синек в jacoco плагин не вызывался, нет surefire.argLine
свойство создано, следовательно, ошибка.
Итак, я возвращаюсь к parent/pom.xml
и создайте это свойство без начального значения:
parent/pom.xml
:
<properties>
<surefire.argLine></surefire.argLine>
</properties>
теперь, когда я строю фу модуль без использования CodeCoverage профиль, я не получаю ошибки:
[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
свойства) и нет targetcode-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.7.0.201403182114org.jacoco.agent-0.7.0.201403182114-runtime.jar=destfile=...footargetcoverage-reportsjacoco-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:...footargetcoverage-reportsjacoco-ut.exec
здесь можно заметить, что jacoco плагин вызывается и устанавливает surefire.argLine
собственность, а surefire.argLine
свойство с пустым значением определено в parent/pom.xml
файл фактически используется для создания argline для верный плагин.
в результате нет , а не targetcode-coverage
каталог, когда я использую CodeCoverage профиль.
я не уверен, что я делаю неправильно здесь. Я объявляю argLine
свойство, как предложено jacoco документация и использование ее всякий раз, когда верный плагин должен указать дополнительные аргумент. Другие ответы на переполнение стека предлагают создать свойство с тем же именем, что и jacoco свойство argLine для обработки случая, когда jacoco не вызывается.
какие предложения?
edit
возможно, одним из решений является явное объявление surefire.argLine
собственность в CodeCoverage профиль, и забудьте об использовании argLine
на jacoco плагин:
<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>
этой верный.argLine свойство для использования агента java, требуемого jacoco плагин, и настроить верный плагин, чтобы использовать это свойство для своих JVM args. The jacoco плагин создаст argLine собственность, но это будет проигнорировано. Это не элегантное решение (так как я делаю предположения о том, как jacoco плагин работает, и это может измениться в будущих версиях).
edit
на jacoco.agent.jar
свойство также должно быть установлено, указав его местоположение в локальном репозитории (не уверен, что это надежно) или используя зависимость плагин для копирования 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>
edit
не уверен, что использует зависимость плагин является правильным подходом или указывает на артефакт агента 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
10 ответов
С jacoco-maven-plugin:prepare-agent
цель выполняется перед плагином maven-surefire -, попробуйте добавить ${argLine}
переменной в argLine
значение, установленное плагином maven-surefire.
пример:
<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.
попробуйте использовать
@{argLine}
вместо
${argLine}
(или surefire.argLine
в вашем случае)
Он позволяет surefire читать свойство, измененное другими плагинами, вместо того, чтобы читать тот, который заменен самим Maven. Затем вы можете установить argLine
param для пустоты в свойствах Maven:
<properties>
<argLine></argLine>
</properties>
который теперь не вызовет никаких проблем. Подробнее здесь: как использовать свойства других плагинов в argLine?
Если ваш проект уже использует argLine для настройки плагина surefire-maven,убедитесь, что 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
попробуйте добавить свойство argLine в разделе свойств (как показано в коде ниже) вместо добавления его в разделе конфигурации плагина maven-sure-fire. Плагин Jacoco maven просто добавит к этому, и все будет работать так, как ожидалось.
<properties>
<argLine>-XX:MaxPermSize=512m</argLine>
</properties>
см.https://docs.sonarqube.org/display/PLUG/Usage + of + JaCoCo + с + Java + плагин
недавно я столкнулся с той же проблемой и даже предпринял неявно те же шаги, что вы описали с тем же результатом. Ни одно чистое решение, которое я нашел, не сработало для меня.
поэтому я выполнил несколько шагов в режиме отладки, и кажется, что Maven заменяет свойства дважды. Это не просто лениво, как я думал, но и нетерпеливо и лениво:
-
готовностью (перед запуском любой цели) заменяются static свойства (определенные в
properties
раздел POM и, вероятно, также настройки.xml), - лениво (перед каждым выполнением) будут заменены динамический свойства.
здесь наш шаг с установкой пустого свойства по умолчанию не удался. Maven просто пошел:
- стремятся заменить значение по умолчанию (пустое)
- JaCoCo устанавливает динамическое значение
- ленивая замена динамических значений (теперь нечего заменять, уже используется пробел значение)
наконец, решение состоит в том, чтобы установить значение по умолчанию динамически. Это можно сделать с помощью плагина 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 идет:
- жаждет замены статических свойств
- GMaven динамически устанавливает значение по умолчанию (если профиль активен)
- JaCoCo устанавливает динамическое значение
- Surefire работает с правильно установленным argLine
С активным профилем файл exec генерируется, с неактивным профилем используется пустое значение по умолчанию, и сборка завершается успешно.
мое решение-использовать несколько профилей.
первый профиль устанавливает пустое значение 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>
при активации профиля гидролокатора профиль не-гидролокатора будет автоматически отключен.
это должно быть немного более элегантно, чем использование других плагинов для работы вы. Теперь вы можете использовать ${surefire.argLine}
переменная в вашем 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>
мое решение использовать argLine в maven-surefire-плагине безопасно.
<plugin>
<groupId>org.codehaus.groovy.maven</groupId>
<artifactId>gmaven-plugin</artifactId>
<version>2.0</version>
<executions>
<execution>
<id>set-custom-arg-line</id>
<phase>validate</phase>
<goals>
<goal>execute</goal>
</goals>
<configuration>
<source>
def argLine = project.properties['argLine'];
if (argLine == null) {
argLine = "";
}
project.properties.argLine = argLine;
</source>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.19.1</version>
<configuration>
<argLine>-Xmx1024m ${argLine}</argLine>
</configuration>
</plugin>
для меня обновление версии с 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 плагин сайта (для сонара) заявляет, что argline должен быть добавлен как свойство. Для меня это также на worken при использовании @{argLine}
В верный настройки плагина.
Я добавил проект Maven/Java С 1 классом домена со следующими функциями:
- модульное или интеграционное тестирование с плагинами Surefire и Failsafe.
- в FindBugs.
- тестовое покрытие через Jacoco.
Я сохранил проект как можно более простым. Проект объединяет множество предложений из этих и других сообщений в примере проекта. Спасибо, вкладчики!
файл readme дает краткое объяснение. В нем объясняется, как можно запустить пользователь или интеграционный тест с помощью Jacoco.
наслаждайтесь!
обновить 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: отчет