metodos - No se pueden usar args jacoco JVM y argumentos JVM infalibles juntos en maven
parametros en java netbeans (10)
Estoy usando maven con el plugin de jacoco para generar métricas de cobertura de código. Tengo dificultades para configurar el plugin surefire con las opciones de java requeridas por el plugin de jacoco . He visto algunas respuestas sobre esto ya en Stack Overflow, pero algo no funciona para mí.
Tengo un proyecto de varios módulos, y uno de mis módulos configura el plugin surefire de la siguiente manera:
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>
Esto funciona como se esperaba
Ahora quiero incorporar a jacoco para obtener métricas de cobertura de código, así que agregué un perfil CodeCoverage que maneja toda la configuración de 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>
Aquí se ve que si se especifica el perfil de CodeCoverage , el complemento jacoco está configurado para usar la propiedad surefire.argLine
, y esa propiedad se usa para configurar argLine
para el plugin surefire .
Luego actualicé el archivo pom.xml para el módulo foo para usar la propiedad surefire.argLine
generada por el complemento 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>
Este enfoque se especifica en la documentación del complemento de jacoco (ver [1]).
Cuando construyo el módulo foo con el perfil CodeCoverage , veo lo siguiente:
[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`
Entonces se ejecuta el plugin jacoco , se crea una propiedad surefire.argLine
, el argLine
para el plugin surefire utiliza la propiedad surefire.argLine
y el argumento MaxPermSize
local, y se genera un archivo target/code-coverage/jacoc-ut-exec
, como se esperaba.
Sin embargo, si no uso el perfil CodeCoverage , aparece un error porque la propiedad ${surefire.argLine}
(utilizada en foo/pom.xml
) no es creada por el complemento de jacoco , y no está definida en ninguna parte:
[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, el complemento de jacoco no fue invocado, no hay una propiedad surefire.argLine
creada, de ahí el error.
Entonces, vuelvo al parent/pom.xml
y creo esta propiedad, sin valor inicial:
parent/pom.xml
:
<properties>
<surefire.argLine></surefire.argLine>
</properties>
Ahora cuando construyo el módulo foo sin usar el perfil CodeCoverage , no obtengo ningún error:
[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`
La línea de comandos infalible ahora es correcta (utilizando la propiedad surefire.argLine
vacía) y no hay target/code-coverage
directorio de target/code-coverage
, como se esperaba.
Así que ahora vuelvo a generar métricas de código, usando el perfil 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
Aquí se puede observar que se invoca el complemento jacoco y establece la propiedad surefire.argLine
, pero la propiedad surefire.argLine
con el valor vacío definido en el archivo parent/pom.xml
se usa realmente para crear el argline para el plugin surefire .
Como resultado, no hay ningún archivo jacoco-ut.exec
, y ningún directorio target/code-coverage
, cuando uso el perfil CodeCoverage .
No estoy seguro de lo que estoy haciendo mal aquí. argLine
una propiedad argLine
como lo sugiere la documentación de jacoco y la uso cada vez que un complemento seguro necesita especificar un argumento adicional. Otras respuestas en Stack Overflow sugieren la creación de una propiedad con el mismo nombre que la propiedad jacoco argLine para manejar el caso cuando no se invoca jacoco .
¿Alguna sugerencia?
editar
Tal vez una solución es declarar explícitamente la propiedad surefire.argLine
en el perfil de CodeCoverage , y olvidarte de usar el argLine
del plugin de 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>
Esto creará la propiedad surefire.argLine para usar el agente de Java requerido por el complemento de jacoco , y configurará el complemento surefire para usar esa propiedad para sus argumentos de JVM. El complemento jacoco ahora creará una propiedad argLine , pero esto será ignorado. No es una solución elegante (ya que estoy haciendo suposiciones sobre cómo funciona el plugin de jacoco , y esto puede cambiar en una versión futura).
editar
La propiedad jacoco.agent.jar
también se debe configurar, señalando su ubicación en el repositorio local (no estoy seguro si esto es robusto) o usando el complemento de dependencia para copiar el contenedor jacoco agent al directorio de compilación local:
<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>
editar
No estoy seguro si el uso del complemento de dependencia es el enfoque correcto, o apuntando al artefacto del agente de jacoco en el repositorio local:
<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>
Esto es más simple y no requiere copiar un artefacto en el directorio de construcción local, pero es frágil: los cambios en el diseño del repositorio lo romperán.
[1] http://www.eclemma.org/jacoco/trunk/doc/prepare-agent-mojo.html
Actualice el POM.xml como
<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>
y luego lo más importante es ejecutar el proyecto Maven con objetivos: mvn jacoco: preparar-agente prueba limpia jacoco: informe
Como el jacoco-maven-plugin:prepare-agent
ejecuta antes del maven-surefire-plugin, intente agregar la variable ${argLine}
en el valor de argLine
establecido por maven-surefire-plugin.
Ejemplo:
<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>
Tuve el mismo problema y esta solución funcionó para mí, sin necesidad de reconfigurar otras secciones del POM.
He agregado un proyecto Maven / Java con 1 clase de dominio con las siguientes características:
- Prueba de unidad o integración con los complementos Surefire y Failsafe.
- Findbugs.
- Prueba de cobertura a través de Jacoco .
Mantuve el proyecto lo más simple posible. El proyecto incluye muchas sugerencias de estas y otras publicaciones en un proyecto de ejemplo. ¡Gracias, contribuidores!
El archivo Léame ofrece una breve explicación. Explica cómo puede ejecutar un usuario o una prueba de integración con Jacoco .
¡Disfrutar!
Intenta usar
@{argLine}
en lugar de
${argLine}
(o surefire.argLine
en su caso)
Permite surefire leer una propiedad modificada por otros complementos en lugar de leer la propiedad sustituida por Maven. Luego puede configurar el argLine
para vaciarlo en las propiedades de Maven:
<properties>
<argLine></argLine>
</properties>
Que ahora no causará ningún problema. Más aquí: ¿Cómo uso las propiedades establecidas por otros complementos en argLine?
Intente agregar la propiedad argLine en la sección de propiedades (como se muestra en el siguiente código) en lugar de agregarla en la sección de configuración del complemento maven-sure-fire. El complemento de maco de Jacoco se agregará a esto y las cosas funcionarán como se espera.
<properties>
<argLine>-XX:MaxPermSize=512m</argLine>
</properties>
Ver https://docs.sonarqube.org/display/PLUG/Usage+of+JaCoCo+with+Java+Plugin
Mi solución es usar múltiples perfiles.
El primer perfil establece un valor en blanco para surefire.argLine
y failsafe.argLine
y está activo de forma predeterminada.
<profile>
<id>not-sonar</id>
<properties>
<surefire.argLine/>
<failsafe.argLine/>
</properties>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
</profile>
El segundo perfil tiene la configuración del complemento jacoco y está inactivo por defecto.
<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>
Cuando active el perfil de sonar, el perfil de no sonar se desactivará automáticamente.
Esto debería ser un poco más elegante que usar otros complementos para hacer el trabajo por usted. Ahora puede usar la variable ${surefire.argLine}
en su argLine y siempre existirá y se establecerá cuando ejecute su compilación.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<argLine>${surefire.argLine} -XX:MaxPermSize=512m</argLine>
</configuration>
</plugin>
Si aún tiene problemas porque $ {surefire.argLine} no tiene un valor, también puede establecer una propiedad ficticia como esta:
<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>
Mi solución para usar argLine en maven-surefire-plugin de forma segura.
<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>
Para mí, actualizar la versión de 0.7.7.201606060606 a 0.7.9 también solucionó esto.
Tuve que agregar explícitamente la versión a la línea de comandos (no solo al pom) porque el servidor de compilación siguió usando la versión anterior. Esto puede hacerse de la siguiente manera:
org.jacoco:jacoco-maven-plugin:0.7.9:prepare-agent
en lugar de
org.jacoco:jacoco-maven-plugin:prepare-agent
El https://docs.sonarqube.org/display/PLUG/Usage+of+JaCoCo+with+Java+Plugin indica que se debe agregar argline como una propiedad. Para mí también funciona cuando se usa @{argLine}
en la configuración del plugin surefire.
Recientemente me encontré con el mismo problema e incluso tomé implícitamente los mismos pasos que describió con el mismo resultado. Ninguna solución limpia que encontré funcionó para mí.
Así que ejecuté varios pasos en modo de depuración y parece que Maven reemplaza las propiedades dos veces. Eso no es solo una manera perezosa, como pensé, sino de manera entusiasta y perezosa:
- con impaciencia (antes de ejecutar cualquier objetivo) se reemplazan las propiedades estáticas (definidas en la sección de
properties
de POM y probablemente también settings.xml), - perezosamente (antes de cada ejecución) se reemplazan las propiedades dinámicas .
Aquí es donde falló nuestro paso para establecer una propiedad en blanco como predeterminada. Maven acaba de ir:
- ansioso reemplazo del valor predeterminado (en blanco)
- JaCoCo establece el valor dinámico
- reemplazo diferido de valores dinámicos (nada que reemplazar ahora, ya usado el valor en blanco)
Finalmente, la solución es establecer el valor predeterminado de forma dinámica. Esto se puede hacer con el complemento de GMaven así:
<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>
Entonces ahora Maven dice:
- ansioso reemplazo de propiedades estáticas
- GMaven establece dinámicamente el valor predeterminado (si el perfil está activo)
- JaCoCo establece el valor dinámico
- Surefire se ejecuta correctamente con argLine
Con el perfil activo se genera el archivo ejecutable, con el perfil no activo se utiliza el valor predeterminado en blanco y la creación se realiza correctamente.
Si su proyecto ya usa el argLine para configurar el complemento surefire-maven, asegúrese de que argLine se define como una propiedad, en lugar de como parte de la configuración del complemento . Por ejemplo:
<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>
La información de cobertura resultante se recopila durante la ejecución y se escribe por defecto en un archivo cuando finaliza el proceso.
Trabajó para mi. Ver: http://www.eclemma.org/jacoco/trunk/doc/prepare-agent-mojo.html