Small question regarding Maven and running unit test please.
I have a very basic Java SpringBoot project, with some unit tests.
I run the basic mvn clean install very straightforward.
For some reason I do not understand, I am seeing all of my unit tests run twice.
one time here:
[INFO] --- maven-surefire-plugin:2.22.2:test (default-test) # project ---
[INFO]
[INFO] -------------------------------------------------------
[INFO] T E S T S
[INFO] -------------------------------------------------------
[INFO] Running MyTest
and one time here:
[INFO] --- maven-surefire-plugin:2.22.2:test (integration-test) # project ---
[INFO]
[INFO] -------------------------------------------------------
[INFO] T E S T S
[INFO] -------------------------------------------------------
[INFO] Running MyTest
And here is my maven:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<testFailureIgnore>true</testFailureIgnore>
<reportsDirectory>target/reports/junit</reportsDirectory>
</configuration>
<executions>
<execution>
<id>integration-test</id>
<goals>
<goal>test</goal>
</goals>
<phase>integration-test</phase>
<configuration>
<excludes>
<exclude>none</exclude>
</excludes>
</configuration>
</execution>
</executions>
</plugin>
May I ask what did I do wrong, as I do not want unit tests to run twice.
Thank you
The Surefire and Failsafe plugins are very similar, and the primary distinction is the phase that they run in. Generally, Surefire runs during the test phase and Failsafe runs during the integration-test phase. (The default configuration has them looking for slightly different test names, such as *Test vs. *IT, to know when to run each.)
You have explicitly told Surefire (the unit-test plugin) to run during integration testing. If you don't want this, simply remove the entire executions stanza. I also strongly recommend against telling Maven not to fail when the tests fail, and changing the report directory is simply likely to confuse tools like CI that are looking in the default location. Best? Take out the plugin definition entirely and use the defaults.
Related
In our jOOQ integration tests, we're using the jOOQ code generation plugin to generate classes into the src/test/java directory. We're doing that because:
We want to check in generated sources, so we can detect regressions in the code generator more easily
The generated classes are used by the tests
So, the (simplified) plugin configuration looks like this:
<plugin>
<groupId>org.jooq</groupId>
<artifactId>jooq-codegen-maven</artifactId>
<executions>
<execution>
<id>some-id</id>
<phase>generate-sources</phase>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<generator>
<target>
<directory>src/test/java</directory>
</target>
</generator>
</configuration>
</execution>
</executions>
</plugin>
Unfortunately, this seems to lead Maven to believe that the classes thus generated need to be compiled as well during the compile phase, as can be seen in the following log output:
[INFO] --- maven-compiler-plugin:3.8.1:compile (default-compile) # ... ---
[INFO] Compiling 25 source files to C:\...\target\classes
[INFO]
[INFO] --- maven-compiler-plugin:3.8.1:testCompile (default-testCompile) # ... ---
[INFO] Compiling 25 source files to C:\...\target\test-classes
... which makes no sense at all. Debug output hints at both src/main/java and src/test/java being included as compileSourceRoots:
[DEBUG] Configuring mojo 'org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile' with basic configurator -->
[DEBUG] (f) compileSourceRoots = [C:\...\src\main\java, C:\...\src\test\java]
For the record, during the testCompile phase, as expected, only src/test/java is placed on the compileSourceRoots path:
[DEBUG] Configuring mojo 'org.apache.maven.plugins:maven-compiler-plugin:3.8.1:testCompile' with basic configurator -->
[DEBUG] (f) compileSourceRoots = [C:\...\src\test\java]
For the record, we're using Maven 3.6.2
How can I prevent the src/test/java directory from being added to the compileSourceRoots variable?
A workaround (not very pretty) is to exclude the test classes from the compiler plugin:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<excludes>
<exclude>com/example/test/**/*.java</exclude>
</excludes>
</configuration>
</plugin>
Another is to use the generate-test-sources phase, which we avoided so far, because of some unrelated side effects that we wanted to test already before the compile phase:
<phase>generate-test-sources</phase>
I'm definitely hoping for a better solution!
I am attempting to configure my Maven project to have unit tests and integration tests. The unit tests are already working fine using the Maven Surefire plugin and are named according to the pattern *Test.java.
After adding the Failsafe plugin, like so:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>2.18.1</version>
<dependencies>
<dependency>
<groupId>org.apache.maven.surefire</groupId>
<artifactId>surefire-junit47</artifactId>
<version>2.18.1</version>
</dependency>
</dependencies>
<configuration>
<includes>
<include>**/*IT.java</include>
</includes>
</configuration>
<executions>
<execution>
<id>integration-test</id>
<goals>
<goal>integration-test</goal>
</goals>
</execution>
</executions>
</plugin>
I added an integration test named SomeTestIT.java. However, when I run:
mvn failsafe:integration-test
I get the following:
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building MyApp 1.0
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-failsafe-plugin:2.18.1:integration-test (default-cli) # MyApp ---
[INFO] Tests are skipped.
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.368 s
[INFO] Finished at: 2015-03-04T14:43:50-06:00
[INFO] Final Memory: 11M/219M
[INFO] ------------------------------------------------------------------------
My test class (buried a few package levels deep beneath the test hierarchy) looks something like:
package com.example.my.package;
import org.junit.Test;
import org.junit.Assert;
import com.example.my.package.SomeService;
import org.junit.runner.RunWith;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.beans.factory.annotation.Autowired;
#RunWith(SpringJUnit4ClassRunner.class)
public class SomeTestIT
{
#Autowired
private SomeService target;
#Test
public void testTest()
{
Assert.assertTrue(false);
}
#Test
public void basicListTest()
{
Assert.assertNotNull(target);
}
}
Where the tests are stubs to make sure that I have the Maven integration working.
I have ensured that:
My POM includes a direct, test scoped dependency on JUnit.
I have tried the plugin configuration both with and without an explicit test runner dependency.
I have tried the configuration above both with and without an explicit include pattern (on the assumption that my class ought to have been picked up by the defaults).
Nonetheless, the tests never actually run. Is there anything else necessary to get the integration tests running?
I finally figured out what was going on and wanted to keep anyone else from spinning their wheels like I did. In the <properties> tag at the head of the POM, someone had added a property that read <skipITs>true</skipITs>. There were no integration tests previously, so the property was useless. It was probably cargo-culted out of some other POM without any real regard for what it is or what it does.
My problem was that maven failsafe plugin was already defined in some parent pom and was configured oddly.
In general, the best way I have found to handle this kind of issues is to first look at the effective pom:
mvn help:effective-pom
and check (1) all properties (2) the configuration of the problematic plugin
IntelliJ users should be sure to check their settings!
As shown in the screenshot below, there is an option in
Settings -> Build, Execution, Deployment -> Build Tools -> Maven -> Runner
If checked, Maven will skip integration tests in the failsafe plugin! It seems to have a similar effect as skipITs in one of the other answers. However, because IntelliJ passes it as an argument to its Maven command, it of course does not show up in the effective POM (also mentioned in a different answer).
I'm having an exceptionally annoying issue with my integration tests, where the Maven failsafe plugin is returning an exit code of 0, regardless of the actual result of the tests:
eg, running 'mvn verify' shows:
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 23.519s
[INFO] Finished at: Tue Sep 16 13:12:55 BST 2014
[INFO] Final Memory: 53M/512M
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-failsafe-plugin:2.6:verify (verify) on project [my.project]: There are test failures.
....
echo $?
0
failsafe config:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>2.17</version>
<executions>
<execution>
<id>integration-test</id>
<goals>
<goal>integration-test</goal>
</goals>
</execution>
<execution>
<id>verify</id>
<goals>
<goal>verify</goal>
</goals>
</execution>
</executions>
</plugin>
I've never seen this issue crop up before and it renders my CI stack worthless, as builds don't fail if the tests fail! The only difference between this and similar things i've done in the past is that i'm using java 8 here.
Solved my own problem - it looks like the stop-jetty execution from the maven jetty plugin was causing strange behaviour with exit codes. Removing the stop-jetty execution fixes the error (and my CI will kill Jetty anyway)
I am literally trying to do exactly this:
http://maven.apache.org/plugins/maven-dependency-plugin/usage.html#The_dependency:build-classpath_mojo
What's amazing is that after finding an explicit example of exactly what I want Maven to do.. I still can't get it to work.
From the command line, I can run ...
mvn -Dmdep.outputFile=classpath.txt dependency:build-classpath
... which does indeed produce a file called classpath.txt with the information I'd like.
I would like to be able to issue a command like "mvn compile" and have the production of this classpath.txt file be a part of that process. The example provided at the link above associates it with generate-sources, which to my understanding should suffice.
When executing a command like "mvn compile" with this pom snippet below, nothing regarding the build-classpath goal seems to execute.
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.8</version>
<executions>
<execution>
<id>build-classpath</id>
<phase>generate-sources</phase>
<goals>
<goal>build-classpath</goal>
</goals>
<configuration>
<outputFile>myfile.txt</outputFile>
<mdep.outputFile>myFile1.txt</mdep.outputFile>
<ihavenoidea>whatgoeshere</ihavenoidea>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>
</build>
And here is what I end up with:
$ mvn compile
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building someproj 1.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) # someproj ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 0 resource
[INFO]
[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) # someproj ---
[INFO] Nothing to compile - all classes are up to date
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.600s
[INFO] Finished at: Fri Jan 31 14:05:29 CST 2014
[INFO] Final Memory: 9M/156M
[INFO] ------------------------------------------------------------------------
$ ls
bin html log pom.xml resources sql src target test-output wwwroot
Your plugin definition is inside <pluginManagement>, which means that when you will declare a "real" execution of that plugin inside a pom that has this pom as parent (or this pom itself), it will use that configuration.
This is generaly a good idea to use <pluginManagement> when a common configuration has to be applied on multiple execution, through multiple modules in the same global project.
Here, I would personally keep the compiler plugin inside <pluginManagement>, as you probably always want that plugin to be configured like this, but I woul move the dependency-plugin inside the <plugins> section (outside the <pluginManagement> section, well yes, this can be confusive...)
You may think of <pluginManagement> as a kind of template. It's often used in parent POMs to define a common configuration. Only plugins in <build><plugins> are included in the build.
That said, Maven does do some "magic" depending on the packaging type. I answered a similar question here.
I need to build my Grails project with Maven, and it is necessary to add an additional grails command. I'm using the grails-maven-plugin to create the pom file, and I can build the war file with $ mvn package
While building this application, I will need to execute another grails command, one the does not correspond directly to any of the maven build phases. Referring to the docs, I'm adding a second execution element to the grails-maven plugin, as follows:
<plugin>
<groupId>org.grails</groupId>
<artifactId>grails-maven-plugin</artifactId>
<version>${grails.version}</version>
<extensions>true</extensions>
<executions>
<execution>
<goals>
<goal>init</goal>
<goal>maven-clean</goal>
<goal>validate</goal>
<goal>config-directories</goal>
<goal>maven-compile</goal>
<goal>maven-test</goal>
<goal>maven-war</goal>
<goal>maven-functional-test</goal>
</goals>
</execution>
<execution>
<id>stats</id>
<phase>init</phase>
<goals>
<goal>exec</goal>
</goals>
<configuration>
<command>stats</command>
</configuration>
</execution>
</executions>
</plugin>
For this example I'm trying to execute grails stats in the maven init phase. (Eventually, stats will be replaced by something more useful.) when I run:
$ mvn package
the ouput includes:
[INFO] [grails:validate {execution: default}]
[INFO] [grails:init {execution: default}]
[INFO] [grails:config-directories {execution: default}]
[INFO] [resources:resources {execution: default-resources}]
which evidently doesn't contain the execution of grails stats. I am able to execute the stats command through Maven directly, in the following way:
$ mvn grails:exec -Dcommand=stats
it only fails to execute when added as a goal in the pom.
I'm using Java 1.5.0_22, Grails 1.3.7, and Maven 2.2.1.
Based on the information I could find about this plugin, you should add the grails: prefix to your goals.
I have no experience with this plugin, so I could be wrong =)
References:
http://grails.1312388.n4.nabble.com/grails-maven-plugin-version-td2284532.html
http://www.grails.org/Maven+Integration
so for example: <goal>grails:init</goal>
OK, my problem was confusing goals and Maven phases. Notice I was trying
<phase>init</phase>
and I had tried other items from the list of goals, but these are not Maven phases.
http://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html