How are non-conflicting configurations resolved if multiple profiles are activated? - maven

Following up this question:
I can't find information on how the union of multiple (active) maven profiles is built, under the condition that they are not conflicting.
Consider the following example:
I want to control how my test cases are run with maven-surefire-plugin. First I need to configure two different environments (jenkins-CI-server) and local. Second I want to enable running different sets of tests.
I would have four profiles:
env_jenkins for running on jenkins
env_local for running on local
testset_A for running some tests
testset_B for running some other tests
Note that for all those profiles I need to define the plugin configuration for the maven-surefire-plugin.
(See below for the concrete xml-configuration)
Then I would like to combine the profiles to run - for example - testset A on jenkins.
My questions:
Is such a behaviour supported by maven?
On which stage does the overriding mentioned in the related question occur? Is the entire plugin configuration overridden (-> my example would not work). Or only really conflicting parts (-> my example would work)?
Does the overriding behaviour depend on the plugin or is it consistent among all maven plugins?
Example pom:
<profiles>
<!-- handle system configurations (e.g. one for jenkins environment, one for local) -->
<profile>
<id>env_jenkins</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<systemPropertyVariables>
<arquillian.launch>jbossas-managed</arquillian.launch>
<jbossHttpPortOverride>8080</jbossHttpPortOverride>
</systemPropertyVariables>
</configuration>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>env_local</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<systemPropertyVariables>
<arquillian.launch>jbossas-managed-jenkins</arquillian.launch>
<jbossHttpPortOverride>${jboss.http.port}</jbossHttpPortOverride>
</systemPropertyVariables>
</configuration>
</plugin>
</plugins>
</build>
</profile>
<!-- define different test sets -->
<profile>
<id>testset_A</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<includes>
<include>TestA1.java</include>
<include>TestA2.java</include>
<include>TestA3.java</include>
</includes>
</configuration>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>testset_B</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<includes>
<include>TestB1.java</include>
</includes>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>

It works using the same inheritance/merging process that works between parent and children POMs. Using the Maven help plugin can confirm this (using Maven 3.3.9):
Order of profile declarations in the POM matters. A plugin configuration inherits the same plugin's configuration declared in an active profile appearing before it in the POM.
The attributes combine.self and combine.children can be used to control the merging.
Example with default settings (without using combine.self or combine.children, i.e. with combine.children="merge" implicitly):
mvn help:effective-pom -Penv_local,testset_A
Effective POM shows merged configurations:
...
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.12.4</version>
<executions>
<execution>
<id>default-test</id>
<phase>test</phase>
<goals>
<goal>test</goal>
</goals>
<configuration>
<includes>
<include>TestA1.java</include>
<include>TestA2.java</include>
<include>TestA3.java</include>
</includes>
<systemPropertyVariables>
<arquillian.launch>jbossas-managed-jenkins</arquillian.launch>
<jbossHttpPortOverride>${jboss.http.port}</jbossHttpPortOverride>
</systemPropertyVariables>
</configuration>
</execution>
</executions>
<configuration>
<includes>
<include>TestA1.java</include>
<include>TestA2.java</include>
<include>TestA3.java</include>
</includes>
<systemPropertyVariables>
<arquillian.launch>jbossas-managed-jenkins</arquillian.launch>
<jbossHttpPortOverride>${jboss.http.port}</jbossHttpPortOverride>
</systemPropertyVariables>
</configuration>
</plugin>
...
Example with combine.self="override":
<profile>
<id>testset_A</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration combine.self="override">
<includes>
<include>TestA1.java</include>
<include>TestA2.java</include>
<include>TestA3.java</include>
</includes>
</configuration>
</plugin>
</plugins>
</build>
</profile>
mvn help:effective-pom -Penv_local,testset_A
Effective POM shows only testset_A's configuration:
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.12.4</version>
<executions>
<execution>
<id>default-test</id>
<phase>test</phase>
<goals>
<goal>test</goal>
</goals>
<configuration combine.self="override">
<includes>
<include>TestA1.java</include>
<include>TestA2.java</include>
<include>TestA3.java</include>
</includes>
</configuration>
</execution>
</executions>
<configuration combine.self="override">
<includes>
<include>TestA1.java</include>
<include>TestA2.java</include>
<include>TestA3.java</include>
</includes>
</configuration>
</plugin>
Example with combine.children="append":
<profile>
<id>testset_A</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration combine.children="append">
<includes>
<include>TestA1.java</include>
<include>TestA2.java</include>
<include>TestA3.java</include>
</includes>
</configuration>
</plugin>
</plugins>
</build>
</profile>
mvn help:effective-pom -Penv_local,testset_A
Effective POM shows merged configurations. In this case, it happens to be the same as the first example. However, had testset_A introduced configuration XML elements that already exist in env_local, they would have been appended:
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.12.4</version>
<executions>
<execution>
<id>default-test</id>
<phase>test</phase>
<goals>
<goal>test</goal>
</goals>
<configuration combine.children="append">
<systemPropertyVariables>
<arquillian.launch>jbossas-managed-jenkins</arquillian.launch>
<jbossHttpPortOverride>${jboss.http.port}</jbossHttpPortOverride>
</systemPropertyVariables>
<includes>
<include>TestA1.java</include>
<include>TestA2.java</include>
<include>TestA3.java</include>
</includes>
</configuration>
</execution>
</executions>
<configuration combine.children="append">
<systemPropertyVariables>
<arquillian.launch>jbossas-managed-jenkins</arquillian.launch>
<jbossHttpPortOverride>${jboss.http.port}</jbossHttpPortOverride>
</systemPropertyVariables>
<includes>
<include>TestA1.java</include>
<include>TestA2.java</include>
<include>TestA3.java</include>
</includes>
</configuration>
</plugin>

Related

Maven plugins via profile are not executed in specified phase

My requirement to execute testng.xml file to run the automation scripts and send the mail once execution is completed. I'll define like what tests to run from testng.xml file.
So I've decided to use maven profiles concept for running the testng.xml file and for sending execution reports as below. When i run the command using
"mvn test -P Code_Compile,Run_Tests,Mail_Reports", below mentioned profiles are not executed. Please let me know what I'm missing here.
<profiles>
<profile>
<id>Code_Compile</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<executions>
<execution>
<id>codecompile</id>
<phase>test</phase>
<goals>
<goal>testCompile</goal>
</goals>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>Run_Tests</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.0</version>
<executions>
<execution>
<id>runtests</id>
<phase>test</phase>
<goals>
<goal>test</goal>
</goals>
<configuration>
<testFailureIgnore>true</testFailureIgnore>
<suiteXmlFiles>
<suiteXmlFile>testng.xml</suiteXmlFile>
</suiteXmlFiles>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>Mail_Reports</id>
<build>
<plugins>
<plugin>
<groupId>ch.fortysix</groupId>
<artifactId>maven-postman-plugin</artifactId>
<version>0.1.6</version>
<executions>
<execution>
<id>send a mail</id>
<phase>test</phase>
<goals>
<goal>send-mail</goal>
</goals>
<inherited>false</inherited>
<configuration>
<from>xx#gmail.com</from>
<subject>Latest Automation Report...</subject>
<failonerror>true</failonerror>
<mailhost>smtp.gmail.com</mailhost>
<mailport>465</mailport>
<mailssl>true</mailssl>
<mailAltConfig>true</mailAltConfig>
<mailuser>xx#gmail.com</mailuser>
<mailpassword>xxxxx</mailpassword>
<htmlMessage><![CDATA[<p>Hi, Please find enclosed latest Automation reports.</p>]]></htmlMessage>
<receivers>
<receiver>xxxx#gmail.com</receiver>
</receivers>
<fileSets>
<fileSet>
<directory>${basedir}/TestReports</directory>
<includes>
<include>LatestAutomationReport.zip</include>
</includes>
</fileSet>
</fileSets>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
I've tried to include only plugins inside build tag instead of profiles by setting the phase as "test" for each plugin as shown below and tried to run "mvn test" command.As you can see below I've included test in each plugin.This try also didn't pick the execution of plugins. Please help me in solving this problem either via profiles or via plugins.
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<executions>
<execution>
<id>codecompile</id>
<phase>test</phase>
<goals>
<goal>testCompile</goal>
</goals>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.0</version>
<executions>
<execution>
<id>runtests</id>
<phase>test</phase>
<goals>
<goal>test</goal>
</goals>
<configuration>
<testFailureIgnore>true</testFailureIgnore>
<suiteXmlFiles>
<suiteXmlFile>testng.xml</suiteXmlFile>
</suiteXmlFiles>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>ch.fortysix</groupId>
<artifactId>maven-postman-plugin</artifactId>
<version>0.1.6</version>
<executions>
<execution>
<id>send a mail</id>
<phase>test</phase>
<goals>
<goal>send-mail</goal>
</goals>
<inherited>false</inherited>
<configuration>
<from>vikascool4#gmail.com</from>
<subject>Latest Automation Report...</subject>
<failonerror>true</failonerror>
<mailhost>smtp.gmail.com</mailhost>
<mailport>465</mailport>
<mailssl>true</mailssl>
<mailAltConfig>true</mailAltConfig>
<mailuser>vikascool4#gmail.com</mailuser>
<mailpassword>vikaschinna</mailpassword>
<htmlMessage><![CDATA[<p>Hi, Please find enclosed latest Automation reports.</p>]]></htmlMessage>
<receivers>
<receiver>vikas.voladri#gmail.com</receiver>
</receivers>
<fileSets>
<fileSet>
<directory>${basedir}/TestReports</directory>
<includes>
<include>LatestAutomationReport.zip</include>
</includes>
</fileSet>
</fileSets>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
If you run mvn fr.jcgay.maven.plugins:buildplan-maven-plugin:1.3:list -P Code_Compile,Run_Tests,Mail_Reportsthis will output the plugins maven is executing and their execution ids, You might see from the output of the command that your executions are probably not overriding the default executions (as these have different ids).
Instead of defining your Code_Compile profile use the default properties defined here: https://maven.apache.org/plugins/maven-compiler-plugin/examples/set-compiler-source-and-target.html
Also if you want to use a specific version of the compiler use pluginManagement to define that.

Running two maven profiles

My profiles in pom.xml
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>2.4.1</version>
<configuration>
<filesets>
<fileset>
<directory>test-output</directory>
<followSymlinks>false</followSymlinks>
</fileset>
</filesets>
</configuration>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>runWithHead</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.18.1</version>
<executions>
<execution>
<id>execution1</id>
<configuration>
<systemPropertyVariables>
<homepage>${ADDRESS}</homepage>
<head>true</head>
<browsers>${browser}</browsers>
<chromeDriverLocation>${chromeDriver}</chromeDriverLocation>
</systemPropertyVariables>
<suiteXmlFiles>
<suiteXmlFile>src/test/resources/testng/testng.xml</suiteXmlFile>
</suiteXmlFiles>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>runHeadlessly</id>
<properties>
<displayProps>target/selenium/display.properties</displayProps>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>selenium-maven-plugin</artifactId>
<version>2.3</version>
<executions>
<execution>
<id>xvfb</id>
<phase>test-compile</phase>
<goals>
<goal>xvfb</goal>
</goals>
<configuration>
<browsers>${browser}</browsers>
<displayPropertiesFile>${displayProps}</displayPropertiesFile>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.18.1</version>
<executions>
<execution>
<id>execution2</id>
<configuration>
<systemPropertyVariables>
<homepage>${ADDRESS}</homepage>
<head>false</head>
<display.props>${displayProps}</display.props>
<browsers>${browser}</browsers>
<chromeDriverLocation>${chromeDriver}</chromeDriverLocation>
</systemPropertyVariables>
<suiteXmlFiles>
<suiteXmlFile>src/test/resources/testng/testng.xml</suiteXmlFile>
</suiteXmlFiles>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
So first we have got shared plugins and then two different profiles.
When i try to run them with one command
mvn clean install -P runHeadlessly,runWithHead
Only plugin with xvfb id gets executed, any ideas?
(did not post the part with default property variables)
You have defined two profiles:
First profile, runWithHead, defines an execution of the maven-surefire-plugin without specifying any goal element (within a goals section), hence an empty execution
Second profile, runHeadlessly, defines an execution and goal of the selenium-maven-plugin plugin AND again an empty execution of the maven-surefire-plugin
As such, both profiles are executed, but effectively only the xvfb of the xvfb execution of the selenium-maven-plugin would be performed.
Since the maven-surefire-plugin has only one goal, test, try to add the following to both executions:
<goals>
<goal>test</goal>
<goals>
Also note: you are configuring additional executions of the maven-surefire-plugin on top of the default default-test execution which will also be executed. Hence, enabling both profiles you will end up with three executions of this plugin.

Maven enforcer append in children

I am using the maven enforcer plugin. Given I have a parent and child pom.xml, I would like that the elements in the exclusions and inclusions tags are appended rather than overridden. I have tried using combine.children="append" for this and it works but I am ending up with an extra configuration tag. Am I using combine.children incorrectly and/or how can I avoid the extra configuration tag? See the example below:
In parent pom.xml:
<project>
[...]
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<version>1.4.1</version>
<executions>
<execution>
<id>enforce-banned-dependencies</id>
<goals>
<goal>enforce</goal>
</goals>
<configuration>
<rules>
<bannedDependencies>
<excludes>
<exclude>org.apache.maven</exclude>
<exclude>org.apache.maven:badArtifact</exclude>
<exclude>*:badArtifact</exclude>
</excludes>
<includes>
<!--only 1.0 of badArtifact is allowed-->
<include>org.apache.maven:badArtifact:1.0</include>
</includes>
</bannedDependencies>
</rules>
<fail>true</fail>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
[...]
</project>
In child pom.xml:
<project>
[...]
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<configuration>
<rules>
<bannedDependencies>
<includes combine.children="append">
<include>org.apache.maven:otherArtifact:2.0</include>
</includes>
</bannedDependencies>
</rules>
</configuration>
</plugin>
</plugins>
</build>
[...]
</project>
Expected effective POM:
<project>
[...]
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<version>1.4.1</version>
<executions>
<execution>
<id>enforce-banned-dependencies</id>
<goals>
<goal>enforce</goal>
</goals>
<configuration>
<rules>
<bannedDependencies>
<excludes>
<exclude>org.apache.maven</exclude>
<exclude>org.apache.maven:badArtifact</exclude>
<exclude>*:badArtifact</exclude>
</excludes>
<includes>
<!--only 1.0 of badArtifact is allowed-->
<include>org.apache.maven:badArtifact:1.0</include>
<include>org.apache.maven:otherArtifact:2.0</include>
</includes>
</bannedDependencies>
</rules>
<fail>true</fail>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
[...]
</project>
Actual effective POM:
<project>
[...]
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<version>1.4.1</version>
<executions>
<execution>
<id>enforce-banned-dependencies</id>
<goals>
<goal>enforce</goal>
</goals>
<configuration>
<rules>
<bannedDependencies>
<excludes>
<exclude>org.apache.maven</exclude>
<exclude>org.apache.maven:badArtifact</exclude>
<exclude>*:badArtifact</exclude>
</excludes>
<includes combine.children="append>
<!--only 1.0 of badArtifact is allowed-->
<include>org.apache.maven:badArtifact:1.0</include>
<include>org.apache.maven:otherArtifact:2.0</include>
</includes>
</bannedDependencies>
</rules>
<fail>true</fail>
</configuration>
</execution>
</executions>
<configuration>
<rules>
<bannedDependencies>
<includes combine.children="append">
<include>org.apache.maven:otherArtifact:2.0</include>
</includes>
</bannedDependencies>
</rules>
</configuration>
</plugin>
</plugins>
</build>
[...]
</project>
If you really want to get the expected merged configuration you should then have in your child module the following:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<executions>
<execution>
<id>enforce-banned-dependencies</id>
<configuration>
<rules>
<bannedDependencies>
<includes>
<include>org.apache.maven:badArtifact:2.0</include>
</includes>
</bannedDependencies>
</rules>
<fail>true</fail>
</configuration>
</execution>
</executions>
</plugin>
That is, reusing the same execution id value in order to point (override/merge) the same execution with additional configuration.
Then the merged effective pom will be as following:
<plugin>
<artifactId>maven-enforcer-plugin</artifactId>
<version>1.4.1</version>
<executions>
<execution>
<id>enforce-banned-dependencies</id>
<goals>
<goal>enforce</goal>
</goals>
<configuration>
<rules>
<bannedDependencies>
<includes combine.children="append">
<include>org.apache.maven:badArtifact:1.0</include>
<include>org.apache.maven:badArtifact:2.0</include>
</includes>
<excludes>
<exclude>org.apache.maven</exclude>
<exclude>org.apache.maven:badArtifact</exclude>
<exclude>*:badArtifact</exclude>
</excludes>
</bannedDependencies>
</rules>
<fail>true</fail>
</configuration>
</execution>
</executions>
</plugin>
Hence, no need to use it: the default merging behavior will suit your needs.
One important note about the usage of combine.* attributes, from official documentation
Note that these attributes only apply to the configuration element they are declared on, and are not propagated to nested elements. That is if the content of an item element from the child POM was a complex structure instead of text, its sub-elements would still be subject to the default merge strategy unless they were themselves marked with attributes.

Maven Profiles Jar issues

I have dev/XYZ.properties file, i am building a jar file using maven -P dev install. How can I place the property file in child.jar/META-INF/XYZ.properties file
You have to execute the maven-resources-plugin:copy-resources goal for your profile dev and bind it with the appropriate phase (process-resources seems the best phase to me). Here is how to define your profile dev :
<profile>
<id>dev</id>
...
<build>
<plugins>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>2.6</version>
<executions>
<execution>
<id>copy-resources</id>
<phase>process-resources</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${basedir}/target/classes/META-INF</outputDirectory>
<resources>
<resource>
<directory>${basedir}/dev</directory>
<includes>
<include>XYZ.properties</include>
</includes>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>

How to run concordion test with maven?

I am wondering how to set up maven to run concordion tests having a FooFixture.java naming convention. The tests are on the classpath in src/test/specs. I would like to do it in a separate profile.
Thanks for the help.
I finally set the tests up is by creating a different profile to run the acceptance tests.
An example given here:
<profile>
<id>acceptance-test</id>
<activation>
<property>
<name>type</name>
<value>acceptance</value>
</property>
</activation>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>1.7</version>
<executions>
<execution>
<id>add-specs-source</id>
<phase>compile</phase>
<goals>
<goal>add-test-source</goal>
</goals>
<configuration>
<sources>
<source>${basedir}/src/test/specs</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.1</version>
<configuration>
<encoding>UTF-8</encoding>
<source>1.5</source>
<target>1.5</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.11</version>
<configuration>
<forkMode>pertest</forkMode>
<argLine>-Xms1024m -Xmx1024m</argLine>
<testFailureIgnore>false</testFailureIgnore>
<skip>false</skip>
<testSourceDirectory>src/test/specs</testSourceDirectory>
<includes>
<include>**/*Fixture.java</include>
</includes>
<systemPropertyVariables>
<propertyName>concordion.output.dir</propertyName>
<buildDirectory>target/concordion</buildDirectory>
</systemPropertyVariables>
</configuration>
</plugin>
</plugins>
</build>
</profile>
You can use the maven failsafe plugin to run unit Concordion tests in the integration-test phase. Its similar to the surefire plugin.

Resources