Mockito, jacoco and surefire causes out of memory - maven

I am using mockito 1.8.3, jacoco 0.72 and maven 3.0.5 surefire plugin (2.12.4) to execute unit test and generating coverage report, it was working fine.
With more and more tests are added, it starts not working. I continuously encounter out of memory error during test execution, and cannot find out a way to figure out what is wrong.
I have about 1800+ test cases with mockito as the mocking tool. It is working fine if I do not run jacoco during maven test with "org.jacoco:jacoco-maven-plugin:prepare-agent " before test phase, but as long as I add jacoco agent, I get OOO issue with PermGen full.
I already added the PermGen to 2GB by modifying MAVEN_OPTS (which should not work since surefire will fork a new process) and surefire argline argument in pom, but it does not help a lot.
I try to get a core dump when OOO occurs by adding parameter to surefire plugin, but never saw a dump file in any folder. I am suspicious that my JVM setting does not work for the surefire plugin, but not sure what is wrong. Anyone could do me a favor? Thanks.
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>${surefire.version}</version>
<inherited>true</inherited>
<configuration>
<properties>
<property>
<name>argLine</name> <value>-server -ea -XX:-UseSplitVerifier -XX:MaxPermSize=2g -Xmx3g -XX:+HeapDumpOnOutOfMemoryError </value>
</property>
<property>
<name>forkMode</name>
<value>once</value>
</property>
<property>
<name>reportFormat</name>
<value>plain</value>
</property>
<property>
<name>skipTests</name>
<value>${maven.test.skip}</value>
</property>
</properties>
</configuration>
</plugin>

You need to set the memory for maven-surefire-plugin like the following:
<plugins>
[...]
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.18.1</version>
<configuration>
<forkCount>3</forkCount>
<reuseForks>true</reuseForks>
<argLine>-Xmx1024m -XX:MaxPermSize=256m</argLine>
<systemPropertyVariables>
<databaseSchema>MY_TEST_SCHEMA_${surefire.forkNumber}</databaseSchema>
</systemPropertyVariables>
</configuration>
</plugin>
[...]
</plugins>

In case you have jacoco configured along with maven failsafe plugin, then you will need to pass memory parameters to that one too:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>2.14.1</version>
<configuration>
<argLine>-Xmx1024m -XX:MaxPermSize=256m</argLine>
</configuration>
</plugin>

Related

Quarkus native executable build: high memory consumption

I'm building a Quarkus native executable with a multi-stage Docker build as described in Quarkus - Building a Native Executable
My project just includes the Hello World-Example with some added ORM-functionality (so not really a lot of dependencies). The build works fine, but my problem is, that it consumes a lot of memory during build time. That means up to 6 GiB. Build time is also very long in my opinion (~4-6 minutes in total).
The problem starts when I'm building on our CI/CD-infrastructure. We don't have that much memory there and so the build fails with Error: Image build request failed with exit status 137.
Am I doing something wrong or is this just the normal behaviour? Is there a possibility to reduce at least the memory consumption?
Thanks to Ken and Luca Burgazzoli! So, it is normal for GraalVM to use >4GiB of RAM and to take more than 3 minutes.
One can limit memory consumption by specifiying -J-Xmx2G as an additionalBuildArgs-param for the quarkus-maven-plugin. But this may increase build time.
#ben answer is correct but maybe it is useful to be more precise. You have to edit the pom.xml in the getting-started dir and edit the native profile and adding <additionalBuildArgs>-J-Xmx2G</additionalBuildArgs> like this:
<profile>
<id>native</id>
<activation>
<property>
<name>native</name>
</property>
</activation>
<build>
<plugins>
<plugin>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-maven-plugin</artifactId>
<version>${quarkus.version}</version>
<executions>
<execution>
<goals>
<goal>native-image</goal>
</goals>
<configuration>
<enableHttpUrlHandler>true</enableHttpUrlHandler>
<additionalBuildArgs>-J-Xmx2G</additionalBuildArgs>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-failsafe-plugin</artifactId>
...
</plugin>
</plugins>
</build>
</profile>
Now, you can limit memory usage from Quarkus:
In your src/main/resources/application.properties file, just set:
quarkus.native.native-image-xmx=2G
Or just pass this option to maven:
mvn package -Dnative -Dquarkus.native.native-image-xmx=2G
If you are using gradle, edit the build.gradle like this:
.
.
.
compileJava {
options.compilerArgs << '-parameters'
}
buildNative {
additionalBuildArgs = [
'-J-Xmx2G'
]
}
So you can limit the memory usage when building with gradle.
With camel quarkus example using maven, I configured as follows to make it work:
<profiles>
<profile>
<id>native</id>
<activation>
<property>
<name>native</name>
</property>
</activation>
<properties>
<quarkus.package.type>native</quarkus.package.type>
<quarkus.native.additional-build-args>-J-Xmx5G</quarkus.native.additional-build-args>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
Using the option <quarkus.native.additional-build-args>-J-Xmx5G</quarkus.native.additional-build-args>

How to pass parameter to maven test

I have One test suite running in two environment.
Sometimes, I would like to run tests in localhost:8080 and sometimes at localhost:8585.
Jenkins run the tests by "mvn test" command.
How could I pass the port by parameter? Something like "mvn test 8080".
I add a plugin on maven pom.xml
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<systemProperties>
<property>
<name>fileName</name>
<value>${fileName}</value>
</property>
</systemProperties>
</configuration>
</plugin>
And get the parameter in junit code with
String fileName = System.getProperty("fileName");
After, I run my tests with -DfileName argument
mvn clean test -DfileName="config-test.xml"
Now, I can put all configurations in xml file and load appropriate file with the corrects parameters.
mvn clean test -DfileName="config-test.xml"
or
mvn clean test -DfileName="config-homolog.xml"
I solved the problem with the tips from Sandra Sukarieh and http://syntx.io/how-to-pass-parameters-to-the-junit-tests-from-the-maven-surefire-plugin/
Thank you very much
try this:
mvn -Dtest=testName -Dargline="-Dport=portValue"
and portValue will be either 8080 or 8585, and while you have a "port" variable declared in your test code.
After doing some research, I found the below code:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<systemProperties>
<property>
<suiteXmlFiles>
<suiteXmlFile>${testsuite}</suiteXmlFile>
</suiteXmlFiles>
</property>
</systemProperties>
</configuration>
</plugin>
Please run the maven command:
mvn test -Dtestsuite =yourxmlsuitepath

How to tell Maven to execute testng tests one by one each in new JVM instance?

Is it possible to tell Maven to execute every testng test in new JVM instance (fork) in serial mode, i.e. one by one.
The configuration below works for junit, but not works for testng
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.9</version>
<configuration>
<forkMode>always</forkMode>
</configuration>
Does anybody know how to set for testng?
#ben75, Thanks for your answer, But it doesn't work for me.
The key point is we use suiteXmlFiles to specify which case to run, and if we use suiteXmlFiles, the forkMode or (forkCount resuseForks) don't work.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.16</version>
<configuration>
<includes>
<include>**/Test*.java</include>
</includes>
<forkMode>always</forkMode>
</configuration>
</plugin>
This configuration works for me.
You can use this
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.16</version>
<configuration>
<forkCount>1</forkCount>
<reuseForks>false</reuseForks>
...
It's a very expensive configuration (i.e. it will take a long time to run your tests... so it's better to not use it, but you probably have some (good ?) reasons to use it).
This solution is the way to go since version 2.14, so I suggest you to upgrade your surefire-plugin version.
the reference is here

How to pass environment variable to process started as mvn jetty:run?

The process started by maven jetty plugin seems ignoring any environment variables I specify.
So far I've tried adding variable through command line like:
set myvariable=1
Also I've tried adding something like "-Dmyvariable=1" to MAVEN_OPTS variable.
Nothing helps.
Just to be clear, I need to pass variable not to maven but to the resulting process, i.e. directly to jetty server.
You need to specify a systemProperties section in the plugin's configuration:
<project>
...
<plugins>
...
<plugin>
<groupId>org.mortbay.jetty</groupId>
<artifactId>maven-jetty-plugin</artifactId>
<configuration>
...
<systemProperties>
<systemProperty>
<name>myvariable</name>
<value>1</value>
</systemProperty>
...
</systemProperties>
</configuration>
</plugin>
</plugins>
</project>

Using custom reporters with the maven surefire plugin

I'm trying to use a custom reporter for TestNG with the maven surefire plugin. I already have a custom listener and that seems to get picked up. However, it doesn't look like the custom reporter is being used at all:
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<testFailureIgnore>false</testFailureIgnore>
<properties>
<property>
<name>listener</name>
<value>com.mystuff.test.TestNGListener</value>
</property>
<property>
<name>reporter</name>
<value>com.mystuff.test.MyEmailableReporter</value>
</property>
</properties>
</configuration>
</plugin>
Any idea why this is happening?
I figured this out. It looked like the following doesn't work at all:
<property>
<name>reporter</name>
<value>com.mystuff.test.MyEmailableReporter</value>
</property>
in spite of documentation to the contrary. In the TestNG class it appears that there is a method called TestNG#addListener(IReporter listener), which contrary to its name, accepts a report which implements IReporter. Maven Surefire (v2.12.1) calls this method to add listeners and reports. However, it doesn't look for reports under a property with name reporter. Instead, you have to add your custom reporter to the listener property:
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<testFailureIgnore>false</testFailureIgnore>
<properties>
<property>
<name>listener</name>
<value>com.mystuff.test.TestNGListener,com.mystuff.test.MyEmailableReporter</value>
</property>
</properties>
</configuration>
</plugin>
Not very intuitive.

Resources