I have two kinds of tests in my Java (Maven) web project: "normal" unit-tests and integration tests using an embedded Tomcat 7 server and Selenium for automated GUI testing on Jenkins. All tests are annotated with JUnit's #Test, normal tests end with "Test.java" while integration tests end with "IntegrationTest.java". All test-classes are located in src/test/java
I normally build my project with mvn clean verify, while the relevant part of my pom.xml which starts the tomcat server and splits the test-categories accordingly looks like this:
<!-- For front-end testing -->
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.2</version>
<configuration>
<uriEncoding>UTF-8</uriEncoding>
<additionalConfigFilesDir>${basedir}/conf</additionalConfigFilesDir>
<contextFile>${basedir}/src/test/resources/context.xml</contextFile>
</configuration>
<executions>
<execution>
<id>start-tomcat</id>
<phase>pre-integration-test</phase>
<goals>
<goal>run-war-only</goal>
</goals>
<configuration>
<fork>true</fork>
<port>9090</port>
</configuration>
</execution>
<execution>
<id>stop-tomcat</id>
<phase>post-integration-test</phase>
<goals>
<goal>shutdown</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.16</version>
<configuration>
<excludes>
<exclude>**/*IntegrationTest*</exclude>
</excludes>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>2.16</version>
<configuration>
<includes>
<include>**/*IntegrationTest*</include>
</includes>
</configuration>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
</execution>
</executions>
</plugin>
This procedure works fine, except when I want to run my tests in eclipse where I normally right-click on my project -> run as -> JUnit Tests. By selecting this option all my tests (including the integration tests) are run. The integration-tests fail in this case because Tomcat is not running (it is only started in Maven's pre-integration-test phase).
How can I exclude these tests in Eclipse with JUnit plugin?
I use junit-toolbox for that. It provides annotations to separate unit and integration tests via wildcard patterns.
<dependency>
<groupId>com.googlecode.junit-toolbox</groupId>
<artifactId>junit-toolbox</artifactId>
<version>2.2</version>
<scope>test</scope>
</dependency>
The base package under e.g. /src/test/java/base contains two classes –
AllUnitTests.java:
package base;
import org.junit.runner.RunWith;
import com.googlecode.junittoolbox.ParallelSuite;
import com.googlecode.junittoolbox.SuiteClasses;
/**
* This detects all (fast running) unit test classes by the given naming pattern.
*
*/
#RunWith(ParallelSuite.class)
#SuiteClasses({ "**/*Test.class", "!**/*IntegrationTest.class", "!**/*LearningTest.class" })
public class AllUnitTests {
}
and
AllIntegrationTests.java:
package base;
import org.junit.runner.RunWith;
import com.googlecode.junittoolbox.SuiteClasses;
import com.googlecode.junittoolbox.WildcardPatternSuite;
/**
* This detects all integration test classes by the given naming pattern.
*
*/
#RunWith(WildcardPatternSuite.class)
#SuiteClasses({ "**/*IntegrationTest.class", "**/*IT.class" })
public class AllIntegrationTests {
}
You can run both generic test suites via Eclipse.
To be able to also run the tests via Maven I use an approach which is similar to the one you have shown.
Related
if I run maven on the command line:
mvn clean install -DskipTests
this actually works and it skips the tests, but if I do it in eclipse, it still always runs the tests
<plugins>
<!-- Maven Assembly Plugin -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<excludes>
<exclude>**/UTest*.java</exclude>
</excludes>
<maven.test.skip>true</maven.test.skip>
<skipTests>true</skipTests>
<!-- get all project dependencies -->
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest> <mainClass>com.example.MyMainClass/mainClass>
</manifest>
</archive>
</configuration>
</execution>
</executions>
</plugin>
So I tried three different ways, all shown above:
1) <skipTests>true</skipTests>
2) <maven.test.skip>true</maven.test.skip>
3) <excludes>...</excludes>
Within eclipse it will always run the tests
The assembly plugin does not run the tests. Maven Works through lifecycle phases. The install phase will trigger (not exhaustive) compiler-plugin, surefire, failsafe, assembly.
More information here, What are Maven goals and phases and what is their difference?
The surefire plugin handles the running of unit tests, to completely skip tests you can add the following to your plugins configuration
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<skipTests>true</skipTests>
</configuration>
</plugin>
Failsafe is an Integration Test runner.
The project is a multi module maven project with 90% of the source code written in Java (there's a small bit in Scala). The unit tests are 80/20 java/scala, and the integration tests are 20/80 java/scala.
I tried Clover, but (at this time) it doesn't support scala.
I tried Jacoco. First I ran into problems getting any results due to the mutli-module configuration, but now using Sonar I've got the java coverage shown (thanks http://www.aheritier.net/maven-failsafe-sonar-and-jacoco-are-in-a-boat/). I used timezra (http://timezra.blogspot.com/2013/10/jacoco-and-scala.html) with jacoco, but that only analyzed the small bit of source code that is scala.
I started to try Scoverage, but that seems to have the same problem as timezra (it analyzes scala-to-scala, not the mix that I have). I therefor haven't even tried scct or undercover.
Is there any tool that handles mixed java/scala?
I would suggest to have two separate coverage tools for Java and Scala. More specifically, use Scoverage for Scala (with plugin for Sonar).
The reason is that for Java you would probably like to measure line coverage where for Scala it's much better to measure statement coverage. Simply said because there are many statements on a single line in Scala and you would like to measure which of them were invoked. I've written an article about this.
to answer my own question, Jacoco does analyze coverage for Scala tests and Java code. I haven't seen anything that does the opposite (but we don't have any Java tests for Scala code, so that didn't matter).
As for combining coverage, Rado's answer of using two tools makes sense.
Here's the changes I did to my pom to get coverage. NOTE, I'm creating Jacoco reports when the test runs, then later using Sonar for more analysis:
properties:
<!-- Jacoco and Sonar config properties -->
<sonar.java.coveragePlugin>jacoco</sonar.java.coveragePlugin>
<sonar.dynamicAnalysis>reuseReports</sonar.dynamicAnalysis>
<jacoco.version>0.7.2.201409121644</jacoco.version>
<sonar-jacoco-listeners.version>1.4</sonar-jacoco-listeners.version>
<jacoco.outputDir>${basedir}/target/</jacoco.outputDir>
<jacoco.out.ut.file>jacoco-ut.exec</jacoco.out.ut.file>
<jacoco.out.it.file>jacoco-it.exec</jacoco.out.it.file>
<sonar.jacoco.reportPath>${jacoco.outputDir}/${jacoco.out.ut.file}</sonar.jacoco.reportPath>
<sonar.jacoco.itReportPath>${jacoco.outputDir}/${jacoco.out.it.file}</sonar.jacoco.itReportPath>
Failsafe:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>2.17</version>
<configuration>
<argLine>-Xms512m -Xmx1024m ${jacoco.agent.it.arg}</argLine>
<properties>
<property>
<name>listener</name>
<value>org.sonar.java.jacoco.JUnitListener</value>
</property>
</properties>
<reportsDirectory>${jacoco.outputDir}/surefire-reports</reportsDirectory>
</configuration>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
</execution>
</executions>
</plugin>
jacoco:
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>${jacoco.version}</version>
<executions>
<execution>
<id>prepare-ut-agent</id>
<phase>process-test-classes</phase>
<goals>
<goal>prepare-agent</goal>
</goals>
<configuration>
<destFile>${sonar.jacoco.reportPath}</destFile>
<propertyName>jacoco.agent.ut.arg</propertyName>
<append>true</append>
</configuration>
</execution>
<execution>
<id>prepare-it-agent</id>
<phase>pre-integration-test</phase>
<goals>
<goal>prepare-agent-integration</goal>
</goals>
<configuration>
<destFile>${sonar.jacoco.itReportPath}</destFile>
<propertyName>jacoco.agent.it.arg</propertyName>
<append>true</append>
</configuration>
</execution>
<execution>
<id>default-report</id>
<phase>package</phase>
<goals>
<goal>report</goal>
</goals>
<configuration>
<dataFile>${sonar.jacoco.reportPath}</dataFile>
</configuration>
</execution>
<execution>
<id>integration-report</id>
<phase>post-integration-test</phase>
<goals>
<goal>report-integration</goal>
</goals>
<configuration>
<dataFile>${sonar.jacoco.itReportPath}</dataFile>
</configuration>
</execution>
</executions>
</plugin>
surefire:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.17</version>
<configuration>
<argLine>${jacoco.agent.ut.arg} -Xms512m -Xmx1024m</argLine>
<skipTests>false</skipTests>
<properties>
<property>
<name>listener</name>
<value>org.sonar.java.jacoco.JUnitListener</value>
</property>
</properties>
<reportsDirectory>${jacoco.outputDir}/surefire-reports</reportsDirectory>
</configuration>
</plugin>
added dependencies:
<dependency>
<groupId>org.codehaus.sonar-plugins.java</groupId>
<artifactId>sonar-jacoco-listeners</artifactId>
<version>${sonar-jacoco-listeners.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.codehaus.sonar.plugins</groupId>
<artifactId>sonar-surefire-plugin</artifactId>
<version>3.3.2</version>
<scope>test</scope>
</dependency>
It is possible to see the mix of the two languages coverage.
With sonar is not possible, because it only analyzes one kind of language.
If you use jenkins, and configure a step that collect coverage reports(Jacoco), you will see the mixing the two languages.
I am doing maven web project in JSf - Richfaces. I have been using "maven clean install" for clearing and build the project to create a war file. It is tedious work to build an entire project for a changes in a single file.
My Question is,
Is there any possibility to build a single java file instead of entire project.
Can we create a short cut or icon in eclipse to build the current project
(ie)"mvn clean install" to create war file
Maven uses incremental compilation i.e. it compiles only classes that changed on disk since the last build.
you can modify your pom.xml , so that "clean, install , deploy" happens automatically. Below is the code that you can append after customizing necessary fields
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.2</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.1</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
<plugin>
<groupId>org.jboss.as.plugins</groupId>
<artifactId>jboss-as-maven-plugin</artifactId>
<version>7.6.Final</version>
<executions>
<execution>
<phase>install</phase>
<goals>
<goal>deploy</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
I need to create a list of subclasses for a particular interface during maven build process and then use that at runtime to load those classes. I have added reflections-maven (from google code reflections) in my webapp pom but during maven build, its only including the classes from the web application and not the classes inside the packaged jars that are there in web-inf/lib folder of that application. Below is the straight forward configuration I have used. I looked at the plugin source code and it seems it scans the following: getProject().getBuild().getOutputDirectory().
Is there anyways I can configure the plugin to scan the dependent jar files of the project?
<plugin>
<groupId>org.reflections</groupId>
<artifactId>reflections-maven</artifactId>
<version>0.9.9-RC1</version>
<executions>
<execution>
<goals>
<goal>reflections</goal>
</goals>
<phase>process-classes</phase>
</execution>
</executions>
</plugin>
You can easily run Reflections with any configuration you like, using, for example, gmaven-plugin:
<plugin>
<groupId>org.codehaus.gmaven</groupId>
<artifactId>gmaven-plugin</artifactId>
<version>1.3</version>
<dependencies>
<dependency>
<groupId>org.reflections</groupId>
<artifactId>reflections</artifactId>
<version>0.9.9-RC1</version>
</dependency>
</dependencies>
<executions>
<execution>
<phase>generate-resources</phase>
<goals>
<goal>execute</goal>
</goals>
<configuration>
<source>
new org.reflections.Reflections("f.q.n")
.save("${project.build.outputDirectory}/META-INF/reflections/${project.artifactId}-reflections.xml")
</source>
</configuration>
</execution>
</executions>
</plugin>
So all you need to do is to use the right configuration, maybe in your specific case:
def urls = org.reflections.util.ClasspathHelper.forWebInfLib()
new org.reflections.Reflections(urls)
.save("${project.build.outputDirectory}/META-INF/reflections/${project.artifactId}-reflections.xml")
Im starting to learn scala and mongo , my IDE is intellij IDEA. I created a scala project using
mvn:archetype-generate
and typed a simple hello world program in the IDEA with some arithmetic options such as
println(5)
val i = 1+2
println(i)
Then i compiled it using
mvn compile
It said
build success
But now how should i execute my application and verify the output. There isn't a single article which explains how to start off with scala,maven,idea and i am entirely new to all of this. any help would be useful for me.
maven-exec-plugin
Try with this code:
package com.example
object Main {
def main(args: Array[String]) {
println(5)
val i = 1 + 2
println(i)
}
}
Place it under /src/main/scala/com/example/Main.scala and run it using:
$ mvn package exec:java -Dexec.mainClass=com.example.Main
If you don't want to pass mainClass manually, you can do this in plugin configuration:
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.1</version>
<configuration>
<mainClass>com.example.Main</mainClass>
</configuration>
</plugin>
</plugins>
There are other possibilities, this is the easiest one. Of course in IntelliJ you should be able to run the program directly.
maven-jar-plugin
If you want to ship the application, use maven-jar-plugin to add Main-Class and Class-Path entries to the manifest:
Main-Class: com.example.Main
Class-Path: lib/scala-library-2.9.0-1.jar lib/slf4j-api-1.6.1.jar ...
The following configuration does that and also copies all the dependencies (including Scala runtime library) to target/lib.
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>2.3.1</version>
<configuration>
<archive>
<manifest>
<mainClass>com.example.Main</mainClass>
<addClasspath>true</addClasspath>
<classpathLayoutType>custom</classpathLayoutType>
<customClasspathLayout>lib/$${artifact.artifactId}-$${artifact.version}$${dashClassifier?}.$${artifact.extension}
</customClasspathLayout>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.3</version>
<configuration>
<outputDirectory>${project.build.directory}/lib</outputDirectory>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
</execution>
</executions>
</plugin>
Now you can simply run your application by (note the target/lib directory is required):
$ java -jar target/your_app-VERSION.jar
You can ship your application simply by copying your JAR file along with /lib subdirectory.
Also see Exec Maven Plugin and Playing with Scala and Maven.