How to execute a method once before maven surefire runs tests - java

I have a test suite which needs to have some setup code to be executed before hand to make sure some data is correct in our database.
We're using the maven surefire plugin to run tests in parallel. ${tests.wildcard} is specified by the profile.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.16</version>
<configuration>
<forkCount>4</forkCount>
<reuseForks>false</reuseForks>
<includes>
<include>${tests.wildcard}</include>
</includes>
</configuration>
</plugin>
I'd like to be able to run a method only once per entire maven execution before surefire runs my tests in parallel. How can I do that?

You could have a special test case which executes your verification code (and fail if the case).
This test case would then be executed by a specific Maven Surefire execution (excluding other tests) and attached to a Maven phase occurring just before the test phase (like process-test-classes): hence, effectively being invoked once per Maven run and before any other test.
Then, the normal test phase would execute any other desired test, excluding the special init test.
An example of such a configuration would be:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.19</version>
<configuration>
<excludes>
<exclude>**/InitTest.java</exclude>
</excludes>
</configuration>
<executions>
<execution>
<id>test-init</id>
<phase>process-test-classes</phase>
<goals>
<goal>test</goal>
</goals>
<configuration>
<test>InitTest</test>
</configuration>
</execution>
</executions>
</plugin>
Note the global configuration for any Surefire execution would exclude the special init test. Then an additional execution would be executed (before the test phase) and would run only the init test (using the <test> element, which takes priority over any other include/exclude).
As such you would have the following flow:
Execute special init test and verify data into database (and fail if required)
Execute any other test
Update
Note that you can achieve the same and perhaps in a more semantically correct way by overriding the default surefire test execution (having default-test execution id) to run the special test (and exclude the others) and then add another surefire execution for the rest (as described above as global configuration, this time as specific execution configuration).
With this approach everything would be attached to the test phase, that's why it would be semantically more correct, although a little bit more verbose in the pom.

Related

Total test execution time - tests running in parallel

I'm trying to retrieve the total [unit]test execution time (surefire for now).
There are couple of places stating we should parse the surefire result (with some text processing) like here
generating the test execution time is not a big problem while tests are running sequentially, but how can I retrieve the test execution time when surefire is configure to run the tests in parallel
for example if I use something like this is pom.xml:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
<configuration>
<parallel>methods</parallel>
<useUnlimitedThreads>true</useUnlimitedThreads>
<threadCount>10</threadCount>
</configuration>
</plugin>
<plugin>
how should I retrieve the overall [unit] test execution time?
Is there any flag added to the result which I can take advantage of?

Two Maven plugin with same execution phase

Is it possible to execute same life cycle of two maven plugin if one fails ?
Example:
Let's say I have below plugin configuration,
<plugins>
<plugin>
<groupId>smothing</groupId>
<artifactId>plugin-1</artifactId>
<version>2.2</version>
<executions>
<execution>
<id>doSomthing</id>
<phase>test</phase>
//...//
</plugin>
<plugin>
<groupId>something</groupId>
<artifactId>plugin-2</artifactId>
<version>2.5</version>
<executions>
<execution>
<id>doSomthingAgain</id>
<phase>test</phase>
//...
</plugin>
</plugins>
I would like to execute plugin-2 test phase even if the first plugin fails. I don't want to ignore or skip test cases.
I have below two plugin to be executed same phase even if one fails.
<groupId>com.thoughtworks.gauge.maven</groupId>
<artifactId>gauge-maven-plugin</artifactId>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
Basically, after the gauge tests I want to perform some cleanup activities through maven exec plugin. So is there any option for me to always execute maven exec plugin ? (No command line arguments, something which I am expecting in pom.xml )
I have seen these answers, but everything says to skip test cases.
How to run a maven goal when there is tests failures?
Maven reporting plugins do not execute if a unit test failure occurs
Any help much appreciated :)
If a plugin fails, it'll stop the execution of the lifecycle. So you shouldn't try to solve it by thinking of executing another plugin for some condition.
Based on your description the best approach seems to be writing an extension, see https://maven.apache.org/examples/maven-3-lifecycle-extensions.html . With https://maven.apache.org/ref/3.6.0/maven-core/apidocs/index.html?org/apache/maven/execution/AbstractExecutionListener.html you can see that you can do actions before or after any segment of the lifecycle, e.g. cleaning up after projectSucceeded+projectFailed

Different Maven configurations for different goals

I have a Maven project which includes a Maven plugin (the Liquibase Maven plugin) which exposes different goals.
Two of these goals (update and diff) need different parameters which are in conflict between them (because the semantics of the two is different), so I need to give Maven different properties in the two goal executions.
That's what I've done
<plugin>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-maven-plugin</artifactId>
<version>3.4.1</version>
<!-- This configuration is used for every goal except "diff" -->
<configuration>
<propertyFile>src/main/resources/liquibase.properties</propertyFile>
<promptOnNonLocalDatabase>false</promptOnNonLocalDatabase>
</configuration>
<executions>
<execution>
<id>default-cli</id>
<goals>
<goal>diff</goal>
</goals>
<!-- This configuration is used for the "diff" goal -->
<configuration>
<propertyFile>src/main/resources/liquibaseDiff.properties</propertyFile>
<promptOnNonLocalDatabase>false</promptOnNonLocalDatabase>
</configuration>
</execution>
</executions>
</plugin>
However, this configuration is wrong because for each goal (diff, update of the others) only the liquibaseDiff.properties file is used.
Is there any way to pass different configurations for different goals in Maven?
Configuration of plugins can be done in two different locations:
Globally for all executions. The global configuration is done with the <configuration> element under <plugin>. This configuration in inherited by all executions.
Per execution. This is done using the <configuration> element under <execution>.
In your example, consider this POM:
<plugin>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-maven-plugin</artifactId>
<version>3.4.1</version>
<configuration>
<!-- put the configuration here that is common to all executions -->
</configuration>
<executions>
<execution>
<id>diff</id>
<goals>
<goal>diff</goal>
</goals>
<configuration>
<!-- put the specific configuration of the diff goal here, this will inherit from the global configuration -->
</configuration>
</execution>
<execution>
<id>update</id>
<goals>
<goal>update</goal>
</goals>
<configuration>
<!-- put the specific configuration of the update goal here, this will inherit from the global configuration -->
</configuration>
</execution>
</executions>
</plugin>
The default inheritance behavior is to merge the content of the configuration element according to element name. If the child POM has a particular element, that value becomes the effective value. If the child POM does not have an element, but the parent does, the parent value becomes the effective value.
In case of conflicts, you can control the default inheritance performed by Maven using combine.children and combine.self. Quoting the Maven docs:
combine.children="append" results in the concatenation of parent and child elements, in that order. combine.self="override", on the other hand, completely suppresses parent configuration.
In addition to this, you need to be aware that when executing a Maven command, on the command line, that directly invokes a goal, such as mvn liquibase:diff, it creates a new execution with an id that is default-cli. As such, since the specific configuration above of the goal diff is done in an execution with id diff, it will not be used. This is actually normal, since the same goal of the same plugin could be present in multiple execution blocks with different configuration: which one should be used if it is executed on the command line, without additional information?
Typically, this situation is solved in 2 manners:
Execute on the command line a specific execution, i.e. the one you configured. This is possible since Maven 3.3.1 and you would execute
mvn liquibase:diff#diff
The #diff in the command above refers to the unique <id> of the execution that is configured in the POM.
Bind your execution to a specific phase of the Maven lifecycle, and let it be executed with the normal flow of the lifecycle. This is generally the prefered solution. In the example above, we could, for example, add a <phase>test</phase> in the execution block of the diff execution; and then Maven will execute it when the test phase is ran during the course of the build.

Adjust assertions for maven tests

I working on a Java/Maven project. I use mvn test to run my test suite. However, in this case all assertions are enabled. Unfortunately this increase the time of some operation from log(n) to n^2 which is rather inconvenient. What is more is that the operation is defined in a dependency packageA whereas I work on packageB. Using plain Java I could add -ea:packageB... to enable only the assertions which I actually need. Is it possible to achieve this behaviour using either the content of the pom.xml or a command line argument to mvn? I know I can disable all assertions but I would rather keep the assertions in the package that I am actually working on...
You can achieve that using surefire-plugin. But first you need to specify profiles for different packages.
Using surefire-plugin you can exclude or include packages, using wildcard or regex.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.18.1</version>
<configuration>
<includes>
<include>%regex[.*[Cat|Dog].*Test.*]</include>
</includes>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.18.1</version>
<configuration>
<excludes>
<exclude>**/TestCircle.java</exclude>
<exclude>**/TestSquare.java</exclude>
</excludes>
</configuration>
</plugin>
You can find more detailed information on this site.
I use these properties:
<maven.test.skip>false</maven.test.skip>
<maven.test.failure.ignore>false</maven.test.failure.ignore>
Then you can leave the Asserts as is, but change these properties to either fail on Assert.fail(), or don't do the tests at all.
Or similarly an extra parameter using CMD, like adding:
-Dmaven.test.skip=true

Maven Surefire only acknowledges "forkMode" on the command line

We have our POM defining the maven-surefire-plugin as follows:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.14</version>
<configuration>
<reuseForks>false</reuseForks>
<forkCount>1</forkCount>
<argLine>-Xms64m -Xmx256m</argLine>
<includes>
<include>**/*Test.java</include>
</includes>
</configuration>
</plugin>
However, our Java tests (which involve some parallel tests and static singletons) only run properly when we run our test phase/build using:
mvn test -DforkMode=always
Strangely, even if we change our <configuration> to use (instead of the newer options):
<forkMode>always</forkMode>
And run:
mvn test
It will fail. But then if we run:
mvn test -DforkMode=always
It will pass. Instead of the newer options, it still will only work if we explicitly provide forkMode on the command line. We have tried this with multiple versions of the surefire plugin, to the same effect.
Are there any locations where this property could be overridden, or known issues in which the XML configuration is not properly used?
Rookie mistake. The configuration I was using was listed in a separate <profile> block that was not being executed. The profile with:
<activeByDefault>true</activeByDefault>
Did not include its own Surefire configuration at all (so it didn't show up in a search), and was using inherited values, which explains why the command-line system properties were able to affect its behavior.

Categories