We're in the middle of developing a big project, with many interacting modules and teams working on said modules. we have implemented CI with jenkins, which does periodic and on-commit builds that run junit tests, fitnesse tests, and cobertura coverage.
Since we're interacting with so many components, for some specific projects we have implemented integration tests, which bring up a Spring context, and run many test cases that simulate significant pieces of the application flow. These are implemented as Junit for simplicity/convenience, are placed in the src/test folders, but are not unit tests.
Our problem is that some component builds are taking very long to run, and one of the identified issues is that the long running integration tests are running twice, once in the test phase and once in the cobertura phase (as cobertura instruments the classes and then runs the tests again). Which leads to the question: is it possible to exclude a test from the cobertura execution?
Using exclude or ignore in the pom cobertura config only works for src/java classes, not the test classes. I couldn't find anything in the cobertura plugin documentation. I'm trying to find a way to do this via configuration. The only other way I think it could be accomplished is to move these tests to another maven module that does not have the cobertura plugin enabled, and have that module be the home of the integration tests. That way the build of the parent pom would trigger the integration tests, but it would not fall under the scope of cobertura. But if it could be done by configuration, it would be so much easier :)
Thanks in advance,
JG
==== UPDATE AND RESOLUTION ====
After building a little on kkamilpl's answer (thanks again!) I was able to include and exclude the needed tests without changing anything in the directory structure. With just java style expressions, once you realize that overrides in the surefire plugin setup, you can manage to run "all but a package"/"only that given package" like this:
<profiles>
<profile>
<id>unit-tests</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<testcase.include>**/*.class</testcase.include>
<testcase.exclude>**/integration/*.class</testcase.exclude>
</properties>
</profile>
<profile>
<id>integration-tests</id>
<properties>
<testcase.include>**/integration/*.class</testcase.include>
<testcase.exclude>**/dummyStringThatWontMatch/*.class</testcase.exclude>
</properties>
</profile>
</profiles>
I was able to run all unit tests (that is, everything but the contents of the integration test folder) with test target and default profile, and then invoke target test with the integration-tests profile to just run the integration test. Then it's a matter of adding the call to the new profile in jenkins as a new top level target call (it targets a parent pom) so that the jenkins build will run the integration tests, but only once, instead of having them re-run by cobertura when it uses the test target.
You can always use maven profiles: http://maven.apache.org/guides/introduction/introduction-to-profiles.html
Separate tests to different directories e.g:
testsType1
SomeTest1.java
SomeTest2.java
testsType2
OtherTest1.java
OtherTest2.java
Next in pom define proper profile for each test type e.g:
<profile>
<id>testsType1</id>
<properties>
<testcase.include>%regex[.*/testsType1/.*[.]class]</testcase.include>
<testcase.exclude>%regex[.*/testsType2/.*[.]class]</testcase.exclude>
</properties>
</profile>
To define the default profile:
<activation>
<activeByDefault>true</activeByDefault>
</activation>
And finally define surefire plugin:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>>
<configuration>
<includes>
<include>${testcase.include}</include>
</includes>
<excludes>
<exclude>${testcase.exclude}</exclude>
</excludes>
</configuration>
</plugin>
To use it call
mvn test #to use default profile
mvn test -P profileName #to use defined profileName
Related
I maintain a small Java component published in Maven Central. In order to successfully publish the artifact, pgp/gpg signature files are required for all the artifacts. Following the directions here: https://central.sonatype.org/pages/apache-maven.html#gpg-signed-components, I can add this plugin to my pom.xml like this no problem.
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
...
and I attach it to the verify or install phase. Now, when I run: "mvn install" or "mvn deploy" the .asc files are generated automatically as desired. Note: you also have to have your pgp/gpg machinery installed and configured properly for this to work.
This works OK for me as the artifact maintainer, but if someone else wants to clone my source code, modify it, and then run mvn install so they can make a locally modified version of the component available to other projects of theirs, they have to have all this pgp/gpg machinery setup properly too, which can be a pain. And they likely don't care about having signature files.
My question is, is there a recommended pom setup so the component maintainer can generate the .asc signature files when needed for a deployment (e.g., to Maven Central), but normal usage of Maven commands don't require signature generation?
I imagine I could use a profile in my pom to handle this. I did figure out a solution, which is pretty simple. Rather than adding the maven-gpg-plugin to my pom, I figured out I can actually just do this:
mvn clean install org.apache.maven.plugins:maven-gpg-plugin:sign deploy
This cleans everything, creates and installs all the artifacts locally, signs all the generated artifacts, and then deploys all the generated artifacts, including the signature files to the deployment target.
This does exactly what I want in 1 line without a pom modification, which is pretty cool. But are there other 'better' ways? Either way, I figured posting this way to do this might be helpful to others.
maven profile
One way using maven-gpg-plugin conditional it is put configuration of maven-gpg-plugin in profile.
You can simplify your profile by only add one property for skip / don't skip maven-gpg-plugin
Your project can look like:
<project ...>
<properties>
<gpg.skip>true</gpg.skip><!-- by default skip gpg -->
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>1.6</version>
<configuration>
<!-- ... -->
</configuration>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>release</id>
<properties>
<gpg.skip>false</gpg.skip>
</properties>
</profile>
</profiles>
</project>
another plugin
You can also consider use another plugin for making signatures, eg: https://www.simplify4u.org/sign-maven-plugin/ sign-maven-plugin by default skips execution if private key not exist on running system.
Another feature of sign-maven-plugin is that don't need external software like gpg to make signature.
gpp.skip property
In my poms I set the gpp.skip property to true:
<properties>
<gpg.skip>true</gpg.skip>
</properties>
Its evaluated by the maven gpg plugin in the way, that signing is skipped by default, e.g.:
mvn install
To enable signing, you can set gpp.skip to false within pom.xml. But better you do it on the command line, so you don't have to modify your pom all the time:
mvn install -Dgpg.skip=false
You can also skip setting the property within the pom and skip signing like this:
mvn install -Dgpg.skip=true
But this way you (and other people working with your project) have to add this all the time to avoid signing. I find it more convenient when signing is turned off by default, as in the first solution. And I guess that's what you want.
I would like to build two different versions of a custom SonarQube (SQ) plugin; one for SonarQube 6.7.x LTS release, one for the latest 7.6 release. At the moment, I have a Maven structure similar to the following:
parent
common: Common code used by both tool and both plugin versions, doesn't use SQ API
tool: Some related command-line utility, doesn't use SQ API
plugin-6.7: Plugin code for SQ 6.7
plugin-7.6: Plugin code for SQ 7.6
dist: Builds a distribution zip containing the CLI utility, both plugin versions, dependency licenses and source code
Most of the source code and resources are the same for both plugin-6.7 and 7.6; only a small number of classes are different. As such I would like to move this common code to some shared source folder/module.
I would still like to compile this common code twice though, to verify the code compiles against both SQ API versions. In Eclipse this should show up as two separate source folders or projects, so I can easily verify that the common code doesn't use any SQ API's that are not yet available in 6.7 API, and doesn't use any API's that have been removed or deprecated in 7.6 API.
Preferably I would like to stick with building both plugin versions in a single build, so if possible I would like to avoid having to use two separate profiles.
Is this possible in any way?
What I have tried
With Maven I have found several ways for getting this to work, but I cannot get any of these approaches to work with m2eclipse.
Approach 1
Create a new module plugin-common, containing pom-6.7.xml and pom-7.6.xml. Both pom's are essentially the same apart from artifact id or classifier, and dependency on different SQ API version. Parent project defines these as 2 separate modules using
<module>plugin-common/pom-6.7.xml</module>
<module>plugin-common/pom-7.6.xml</module>
The issue with this approach is that I can't import these modules into Eclipse, as m2eclipse only supports pom.xml as the filename.
Approach 2
Similar to the above, but using separate sub-directories for the pom.xml files and using <sourceDirectory>${project.basedir}/../src/main/java</sourceDirectory> to point to the common source code:
plugin-common
src/main/java
src/main/resources
pom.xml: parent for 6.7 and 7.6 modules
6.7/pom.xml
7.6/pom.xml
This approach allows for importing both plugin-common versions into Eclipse, but Eclipse complains about 'Access .../src/main/java directory outside of project base directory'. As such it doesn't show any source code in the two plugin-common projects.
Approach 3
Don't have any pom.xml files in plugin-common, but instead add the common code as source folders to both plugin-6.7 and plugin-7.6 modules using build-helper-maven-plugin, using <source>${project.basedir}/../plugin-common/src/main/java</source>.
Again this fails in Eclipse due to the 'Access .../src/main/java directory outside of project base directory' warning.
I have now opted for the following approach, which works quite well.
Maven structure:
parent
common: Common code used by both tool and both plugin versions, doesn't use SQ API
tool: Some related command-line utility, doesn't use SQ API
plugin: SonarQube plugin code
dist: Builds a distribution zip containing the CLI utility, both plugin versions, dependency licenses and source code
The plugin module contains 3 base packages:
myproject.plugin.common: Code shared between SQ 6.7 and 7.6 implementations
myproject.plugin.sq67: Code specific for SonarQube 6.7 - 7.5.x
myproject.plugin.sq76: Code specific for SonarQube 7.6+
The plugin/pom.xml uses SonarQube API dependency and packaging plugin definitions similar to the following:
<dependency>
<groupId>org.sonarsource.sonarqube</groupId>
<artifactId>sonar-plugin-api</artifactId>
<version>${sonarqube.version}</version>
<scope>provided</scope>
</dependency>
<plugin>
<groupId>org.sonarsource.sonar-packaging-maven-plugin</groupId>
<artifactId>sonar-packaging-maven-plugin</artifactId>
<version>1.16</version>
<extensions>true</extensions>
<configuration>
<pluginKey>mykey</pluginKey>
<pluginClass>myproject.plugin.common.MyPlugin</pluginClass>
<pluginName>PluginName</pluginName>
<pluginDescription>Description</pluginDescription>
<useChildFirstClassLoader>true</useChildFirstClassLoader>
<sonarQubeMinVersion>6.7</sonarQubeMinVersion>
</configuration>
</plugin>
This allows the plugin to work with SonarQube 6.7+, even if the API dependency version is set to 7.6 (see profiles below). The MyPlugin class is a generic class that uses Java reflection to load a 6.7-specific or 7.6-specific implementation depending on the SonarQube version that the plugin is running in.
Finally, the parent pom.xml defines the following two profiles:
<profiles>
<profile>
<id>default</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<sonarqube.version>7.6</sonarqube.version>
</properties>
<modules>
<module>common</module>
<module>plugin</module>
<module>tool</module>
<module>dist</module>
</modules>
</profile>
<profile>
<id>checkSQ6.7Compatibility</id>
<activation>
<activeByDefault>false</activeByDefault>
</activation>
<properties>
<sonarqube.version>6.7</sonarqube.version>
</properties>
<modules>
<module>common</module>
<module>plugin</module>
</modules>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<excludes>
<exclude>**/sq76/**</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
The default profile now builds a plugin that is compatible with SonarQube 6.7 and up, with 7.6-specific features enabled if running on that version of SonarQube.
The checkSQ6.7Compatibility profile overrides the SonarQube API version to 6.7, excludes any SonarQube 7.6-specific folders, and only builds the common and plugin modules (skipping tool and dist). This allows for verifying that the common and 6.7-specific packages compile OK with the 6.7 API.
In Eclipse, I now use the default profile for regular development, allowing me to work on both 6.7 and 7.6 specific code at the same time. After any major changes, I can simply select the checkSQ6.7Compatibility profile in the Eclipse project configuration, in order to verify that I haven't accidentally introduced a dependency on any 7.6-specific API's.
I would like to know if using IntelliJ, is possible to run all test in the visual environment choosing a specific Junit category.
At the moment if you execute:
mvn clean test
you execute Fast Tests, but how to use IntelliJ to choose Slow or Fast?
Fragment of pom.xml
<profiles>
<profile>
<id>SlowTest</id>
<properties>
<testcase.groups>YOUR.PROJECT.test.categories.Slow</testcase.groups>
</properties>
</profile>
<profile>
<id>FastTest</id>
<properties>
<testcase.groups>YOUR.PROJECT.test.categories.Fast</testcase.groups>
</properties>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
</profile>
</profiles>
Many thanks in Advance
Juan Antonio
Your profiles are focusing the test run on specific categories. The JUnit Run/Debug configuration in IntelliJ also allows you to focus a JUnit run on a specific category.
You can access this configuration window from Run > Edit Configurations
Here's a screenshot showing a saved confoguiraiton named SlowTests which runs all tests having the category: com.stackoverflow.surefire.SlowTests:
You can save any such configuration by clicking on the file icon in the top left hand corner of this window and then that configuration will be available in the Run menu and you can even associate a keyboard short cut with it.
More information in the docs.
If you created your project using the pom.xml, in the "Maven Projects"-View you can activate the profiles you want to be active. There (Lifecycle) you can start the goal you want to be executed for each module as well.
How to get this: View->Tool Windows->Maven Projects
I have configured my Jenkins/Maven project, it reads my TestNG test from POM file configuration where is test.xml file with instructions which tests to run.
If I will add more tests to XML file (for example Test1 and Test2), they will be dependent on the same POM file, and when I create a job in Jenkins, both tests will run in one Jenkins job.
My question is:
How to configure Maven or Jenkins to be able to create two separate Jobs in Jenkins (Job Test1 and Job Test2) but using the single POM file?
My suggestion would be - create different Maven's profiles and execute it for specific Jenkin's job.
For example, you have 2 different test classes, you can create a specific profile for each at pom file:
<profiles>
<profile>
<id>test1</id>
<properties>
<suite.pattern>**/TestOne.java</suite.pattern>
</properties>
</profile>
<profile>
<id>test2</id>
<properties>
<suite.pattern>**/TestTwo.java</suite.pattern>
</properties>
</profile>
now you can run them separately:
mvn clean test -P test1
or
mvn clean test -P test2
Thus, you can configure two Jenkins jobs.
I have found another solution.
In Jenkins Project configuration need to write the command like this:
-Dtest=FirefoxTest2.java clean test
Do not need to add any additional information about java classes in POM file.
Just got a strange error. Working on project using JUnit and Maven 3.0.3 I've created in my test/src/java folder one test class - ClassifierUtilTest.java, with #Test-annotated methods and stuff, and two utility classes, just for the use in the testing env (one with few static methods for bypassing private visibility scopes and one mock for tested interface).
It works good under Maven 3.0.3 (mvn test), and in Eclipse 3.7 (run as / JUnit test), but when someone else tried to 'mvn test' it with Maven 2.2.1 it failed. Apparently it tried to treat those util classes as test classes and failed due to 'no #Test-annotated methods' and 'more than one constructor'.
It's not JUnit fault (at least it shouldn't be, maven dependency is the same, junit:junit:4.9), so it seems to be strictly maven or maven-surefire-plugin fault. I was wondering if there is some widely-known workaround for Maven 2.2.1 for this problem?
maven-surefire-plugin by default runs all the classes the have Test prefix or suffix (like yours ClassifierUtilTest) and TestCase suffix. Just change the name to ClassifierTestUtil and you'll be fine.
You can also exclude certain files/directories in pom.xml, see Inclusions and Exclusions of Tests:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.11</version>
<configuration>
<excludes>
<exclude>**/ClassifierUtilTest.java</exclude>
</excludes>
</configuration>
</plugin>