How to get unit tests to run in Maven Tycho build? - java

I've done a lot of work in the past writing unit tests that run in "conventional" Maven builds,
using JUnit and Mockito (and PowerMock). I'm now working on an Eclipse plugin codebase, which builds with Maven Tycho.
Overall, it's a multiproject build, but I'm only adding unit tests to one of the plugin projects (for now).
I've heard of tycho-surefire, but that seems pretty complicated, and it really sounds more like it supports integration tests instead of unit tests. I'm guessing I'll probably have no choice but to use this, but so far I haven't tried to integrate it.
I tried getting the JUnit and Mockito artifacts from Maven, and then using the maven-dependency-plugin to get the artifacts available to be referenced in the Bundle-Classpath property of the manifest.
When I run the build, the tycho-compiler-plugin I see it compiling 105 source files, which includes all of the classes in src/main/java and src/test/java.
It fails to compile the test class because it can't find the Mockito classes, even though when I run the build with -X, it shows the mockito-all artifact in the dependency tree.
What can I do here?

After a lot of painful Maven trial & error I struggled across this website, which provides a surprisingly easy way to use unit-tests in a Maven-Tycho setup.
Here, the important parts of the pom.xml when using JUnit (probably looks similar for Mockito):
<testSourceDirectory>src/test/java</testSourceDirectory>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.12.4</version>
<executions>
<execution>
<id>test</id>
<phase>test</phase>
<configuration>
<includes>
<include>**/*Test.java</include>
</includes>
</configuration>
<goals>
<goal>test</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.5.1</version>
<executions>
<execution>
<id>compiletests</id>
<phase>test-compile</phase>
<goals>
<goal>testCompile</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
Name all your tests in a way so that they end with *Test.java. Run mvn test in order to execute all available unit-tests.

You have to use junit and Mockito as osgi bundles
I think this Question answered detailed here
I hope this helps.

Related

How to configure maven and intellij to include parameters compiler flag for both groovy and java

Hey I am writing this since I spent some time trying to configure Jackson's ObjectMapper to work without #JsonCreator and #JsonProperty annotations on my DTOs. The result I wanted to achieve is to be able to run Spock's tests (groovy) in both intellij and in console with maven.
Since this issue is resolved: https://youtrack.jetbrains.com/issue/IDEA-125737 intellij automatically picks up below maven configuration:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<compilerArgument>-parameters</compilerArgument>
<testCompilerArgument>-parameters</testCompilerArgument>
</configuration>
</plugin>
Also if you want to use Spock for testing in groovy you need following plugin configuration:
<plugin>
<groupId>org.codehaus.gmavenplus</groupId>
<artifactId>gmavenplus-plugin</artifactId>
<version>${gmavenplus-plugin.version}</version>
<configuration>
<parameters>true</parameters>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>compileTests</goal>
</goals>
</execution>
</executions>
</plugin>
plus additional information:
At the moment I was writing this there was only one version of groovy compiler that worked for me: 2.5.0-alpha-1
maven-compiler-plugin version I used was 3.7.0. Version 3.1 did not work at all. I did not try others.
I hope this saves someone some time :)

Maven aggregation build uses different java than building a child module on its own

I noticed an unexpected behavior. I have an aggregation POM for the purposes of aggregated goals execution.
When I execute the build task, the modules included in aggregation POM have their javadoc generated. The javadoc generation is defined in parent POM (not the same as aggregation POM) like this:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.9.1</version>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
The child module has its own POM, in which an aspectJ plugin is defined like this: (this is how the build tag actually looks like as a whole in the child POM:
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.6</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
<complianceLevel>1.7</complianceLevel>
<verbose>true</verbose>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
<dependencies>
</dependencies>
</plugin>
</plugins>
</build>
Now, when I run the aggregation build, it generates javadocs with Java 1.8 (there is no mention about which java to use in aggregation POM):
Constructing Javadoc information...
Standard Doclet version 1.8.0
Building tree for all the packages and classes...
...
12 errors
16 warnings
But when I run build just on the child module, it will use Java 1.7.0_45
Constructing Javadoc information...
Standard Doclet version 1.7.0_45
Building tree for all the packages and classes...
...
2 warnings
Why this inconsistency? I would expect that the build should work the same. Am I doing something wrong? How does one configure the aggregation build to use the configuration of the child module (with its POM), which to me seems the way which should be default.
My assumption is that aggregation build is the same thing as running "install" goal on each child module manually as if on a seperate project. Is this assumption wrong? (seems like it is, since this behaviour) If yes, what is actually happening?
If information are missing (parts of pom configurations) please comment.

Maven checkstyle https configuration

I have the following maven check style plugin configuration
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
<configuration>
<consoleOutput>true</consoleOutput>
<configLocation>https://someUtl.com/file.xml</configLocation>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
</plugin>
Pay attention on
<configLocation>https://someUtl.com/file.xml</configLocation>
file.xml can be downloaded by browser, but it require a login and password. Is there a way to specify these login/password in maven or in plugin configuration?
Underneath, this uses Plexus which in turn pretty much does URL.openStream().
This answer shows how an Authenticator can be used for that in Java code, but I was unable to find a Maven equivalent for that. I'm inclined to say that it's not possible.
Alternatively, you might be able to download the file in a separate mojo execution, then point the configLocation to the downloaded file, which could be anywhere down your target folder.
I think that this answer gives a few nice ideas about how to download files in Maven. Their first is that if your file is a Maven artifact, you could use the Maven Dependency Plugin.
And then we come full circle, because if your Checkstyle configuration were to be contained in a Maven artifact, you would not have to set configLocation to a remote location, but you'd add that artifact as a dependency of your Checkstyle plugin execution. Since Maven defines everything in terms of dependencies, that is my way to go, and that is exactly how I set up my own Checkstyle configurations.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>com.totaalsoftware.incidentmanager</groupId>
<artifactId>checkstyle-config</artifactId>
<version>2.0.0-SNAPSHOT</version>
</dependency>
</dependencies>
<configuration>
<configLocation>checkstyle.config.xml</configLocation>
...
</configuration>
</plugin>
Clearly, in the above example, checkstyle.config.xml resides in the root of the checkstyle-config JAR.

Maven 2.2.1 attached tests. Issue -Dmaven.test.skip=true

I am using the plugin to attached tests in the test of another module.
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.2</version>
<executions>
<execution>
<goals>
<goal>test-jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
And in the module where the jar is required:
<dependency>
<groupId>com.myco.app</groupId>
<artifactId>foo</artifactId>
<version>1.0-SNAPSHOT</version>
<type>test-jar</type>
<scope>test</scope>
</dependency>
</dependencies>
It has been very useful to me, but I have found a problem: When I execute "clean install -Dmaven.test.skip=true", also the dependency test-jar is required and the proccess fails
yes, because -Dmaven.test.skip=true just makes the maven junit plugins (surefire and failsafe) not execute - it prevents them from running any tests.
it does NOT prevent maven from trying to "collect" all of your test-scoped dependenies. maven still collects all of them.
if you want optional dependencies (regardless of what scope) you should read about maven profiles - you could define a profile in which this dependency will be defined and then maven will try and get it only if you activate the profile (from the command line, for example)
-Dmaven.skip.test or -DskipTests just skips the test execution, it still compiles test classes so it needs test dependencies
If you want to skip the compilation of test classes, you can configure maven compiler plugin to do so, more helpful would be to create separate build profile and skip compilation on demand by specifying special build profile
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<executions>
<execution>
<id>default-testCompile</id>
<phase>test-compile</phase>
<goals>
<goal>testCompile</goal>
</goals>
<configuration>
<skip>true</skip>
</configuration>
</execution>
</executions>
</plugin>

How to exclude java classes from being compiled in maven with annotation

I already have a working solution where I can specify with maven which classes to not compile when using a particular maven profile.
But I would like to use a general solution and use an annotation instead
The current solution that I have is like
<plugin>
<!-- Exclude some web services used only for internal testing -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<optimize>true</optimize>
<excludes>
<exclude>**/something/*ClassPattern.java</exclude>
</excludes>
<testExcludes>
<exclude>**/something/*ClassPatternTest.java</exclude>
</testExcludes>
</configuration>
</plugin>
But Some thing like
#NotCompiledForProduction
would be rather nice on top of a class.
It seems to me that this might be hard (or impossible to do) without changing maven's behaviour. That is not the scope here. And this kind of annotation
You cannot (I assume) use an annotation to determine what source code gets presented to the java compiler, because you need to compile the source code in the first place to process the annotation.
It seems like you need to create different modules in your maven project: one that generates a jar file with the production code, and one module that generates a jar file with testing implementation with a dependency on the production artifact.
If the code really does need to be in the same maven module, then the code should always be compiled. You can however use maven-jar-plugin to create multiple artifacts at the package phase: the default artifactId.jar, and an artifactId-test-lib.jar artifact. You can do this by specifying multiple executions for the plugin, and using <includes> and <excludes> to split the jar files as required.
you can try this...
<build> <plugins>
<!-- Run annotation processors on src/main/java sources -->
<plugin>
<groupId>org.bsc.maven</groupId>
<artifactId>maven-processor-plugin</artifactId>
<executions>
<execution>
<id>process</id>
<goals>
<goal>process</goal>
</goals>
<phase>generate-sources</phase>
</execution>
</executions>
</plugin>
<!-- Disable annotation processors during normal compilation -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<compilerArgument>-proc:none</compilerArgument>
</configuration>
</plugin>
</plugins> </build>

Categories