I have an Eclipse Java project for which I am trying to execute the unit tests using Maven.
I have my unit tests as below so that it respects the expected hierarchy
src/test/java/StringUtilsTests.java
However, my unit test references the source code located in:
src/my/package/root/util/StringUtils.java
just because it has always been like this and I don't want to change my folder hierarchy for the tests.
Therefore, I use the build-helper-maven-plugin to add this source folder, as below
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>3.2.0</version>
<executions>
<execution>
<id>add-test-source</id>
<phase>generate-test-sources</phase>
<goals>
<goal>add-test-source</goal>
</goals>
<configuration>
<sources>
<source>src/my/package/root/util</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
But even with that, I get the below error:
[INFO] -------------------------------------------------------------
[ERROR] COMPILATION ERROR :
[INFO] -------------------------------------------------------------
[ERROR] /C:/Users/frederic/git/myproject/src/test/java/StringUtilsTests.java:[22,32] package package my.package.root.util does not exist
Below is my reference to the maven-surefire-plugin
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M5</version>
<configuration>
<skipTests>false</skipTests>
</configuration>
<executions>
<execution>
<goals>
<goal>test</goal>
</goals>
</execution>
</executions>
</plugin>
And it's even worse if I don't put my test in
src/test/java/StringUtilsTests.java
but instead here for example:
src/tests/my/package/root/util/StringUtilsTests.java
The maven-surefire-plugin will show
No tests to run
Do you need to run them as Unit-Tests or can you run them as Integration-Tests? I think Integration tests would work out-of-the-box like this? Simply change the class names to end with IT MyClassIT.java for these tests or finetune your .pom and change the goal to integration-test-phase or verification-phase? I think that should work since it will be executed later on in the build cycle.
Otherwise try to change this line with a wildcard:
<source>src/my/package/root/util/*</source>
Based on this article, adding the below elements to my pom.xml fixed my issue:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<executions>
<execution>
<id>compiletests</id>
<phase>test-compile</phase>
<goals>
<goal>testCompile</goal>
</goals>
</execution>
</executions>
</plugin>
<testSourceDirectory>${project.basedir}/src-test</testSourceDirectory>
And VERY important was to add this dependency
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.8.1</version>
<scope>test</scope>
</dependency>
Related
I'm trying to add some Kotlin classes into my existing Java project under Vaadin Framework (v 8.4.5).
I've fully read the tutorial on how to mixing java and Kotlin, and I've successfully created a Kotlin class inside my existing Java Project.
The new Kotlin class is inside my project (ofc I've cutted away all code for privacy)
package it.projectName.utils
import it.projectName.otherClasses
class SecurityUtils (user: User) {
//various val and var, and of course the isCrypted calculated val
init {
if(!isCrypted){
//encrypt user password
}
}
}
Now I'm using this Kotlin class inside my Java class with
import it.projectName.utils.SecurityUtils;
public class UserDao{
//[... other code ...]
SecurityUtils securityUtils = new SecurityUtils(user);
}
Everything is fine, I don't get any compiler error.
But when I try to run my project with maven with jetty:run , it throws an error:
[ERROR] COMPILATION ERROR :
[INFO] -------------------------------------------------------------
[ERROR] /C:/pathToClass/UserDao.java:[9,36] cannot find symbol
symbol: class SecurityUtils
location: package it.projectName.utils
[INFO] 1 error
[INFO] -------------------------------------------------------------
The line he's referring to is import it.projectName.utils.SecurityUtils;
I've checked my pom.xml, everything looks fine there aswell:
<properties>
<kotlin.version>1.2.61</kotlin.version>
<kotlin.compiler.incremental>true</kotlin.compiler.incremental>
</properties>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib-jdk8</artifactId>
<version>${kotlin.version}</version>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-test</artifactId>
<version>${kotlin.version}</version>
<scope>test</scope>
</dependency>
<plugin>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-plugin</artifactId>
<version>${kotlin.version}</version>
<executions>
<execution>
<id>compile</id>
<phase>compile</phase>
<goals>
<goal>compile</goal>
</goals>
<configuration>
<sourceDirs>
<sourceDir>src/main/java</sourceDir>
<sourceDir>src/main/kotlin</sourceDir>
</sourceDirs>
</configuration>
</execution>
<execution>
<id>test-compile</id>
<phase>test-compile</phase>
<goals>
<goal>test-compile</goal>
</goals>
<configuration>
<sourceDirs>
<sourceDir>src/main/java</sourceDir>
<sourceDir>src/main/kotlin</sourceDir>
</sourceDirs>
</configuration>
</execution>
</executions>
<configuration>
<jvmTarget>1.8</jvmTarget>
</configuration>
</plugin>
What I'm missing?
Thanks
We have to use two different source directories for each, under the src/main directory. (I'm talking about maven folder structure).
For example for Java, it is src/main/java and for Kotlin, it's like src/main/kotlin.
As per the documentation here, under topic of Compiling Kotlin and Java sources, JetBrains provides comprehensive maven plugin to declare each of aforementioned directories as their corresponding source directory. So then the compiler can detect both source directories, and in the building process, able to copy respective binary files to the class path.
Here is that maven plugin declaration,
<build>
<plugins>
<plugin>
<artifactId>kotlin-maven-plugin</artifactId>
<groupId>org.jetbrains.kotlin</groupId>
<version>${kotlin.version}</version>
<executions>
<execution>
<id>compile</id>
<goals> <goal>compile</goal> </goals>
<configuration>
<sourceDirs>
<sourceDir>${project.basedir}/src/main/kotlin</sourceDir>
<sourceDir>${project.basedir}/src/main/java</sourceDir>
</sourceDirs>
</configuration>
</execution>
<execution>
<id>test-compile</id>
<goals> <goal>test-compile</goal> </goals>
<configuration>
<sourceDirs>
<sourceDir>${project.basedir}/src/test/kotlin</sourceDir>
<sourceDir>${project.basedir}/src/test/java</sourceDir>
</sourceDirs>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<executions>
<!-- Replacing default-compile as it is treated specially by maven -->
<execution>
<id>default-compile</id>
<phase>none</phase>
</execution>
<!-- Replacing default-testCompile as it is treated specially by maven -->
<execution>
<id>default-testCompile</id>
<phase>none</phase>
</execution>
<execution>
<id>java-compile</id>
<phase>compile</phase>
<goals> <goal>compile</goal> </goals>
</execution>
<execution>
<id>java-test-compile</id>
<phase>test-compile</phase>
<goals> <goal>testCompile</goal> </goals>
</execution>
</executions>
</plugin>
</plugins>
Also, I personally recommend following property must be there to increase the speed of build process.
<properties>
<kotlin.compiler.incremental>true</kotlin.compiler.incremental>
</properties>
This one had worked for me pretty well, even if you creating a maven project with modules.
Can you tell me how to call maven surefire in command line with the following configuration ?
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.19.1</version>
<executions>
<execution>
<id>Custom tests</id>
<phase>test</phase>
<goals>
<goal>test</goal>
</goals>
<configuration>
<classesDirectory>target/generated/classes/normalCase/</classesDirectory>
<reportsDirectory>target/generated/reports/normalCase/</reportsDirectory>
</configuration>
</execution>
</executions>
</plugin>
When surefire is defined like this in my pom.xml and I execute the phase test, it work exactly how i want it to work : it tries to run my tests on the classes located in target/generated/classes/normalCase.
So I tried this command line:
mvn surefire:test -DclassesDirectory="target/generated/classes/normalCase/"
But no, it keep checking the classes in the default value directory which is "target/classes".
So how can I achieve this in command line ?
To recap the situation you have. You are generating multiple version of your source code during the build, each of those version ends up in a separate folder under target. For each of those versions, you would like to execute your unit tests with the maven-surefire-plugin. Let's consider the base directory to be target/generated/classes. That means you have multiple subdirectories target/generated/classes/version1, target/generated/classes/version2... for each version.
A possible solution would be to use the iterator-maven-plugin to iterate over all subdirectories of a folder and invoke the maven-surefire-plugin from all those subdirectories. The variable #item# holds the current item.
<plugin>
<groupId>com.soebes.maven.plugins</groupId>
<artifactId>iterator-maven-plugin</artifactId>
<version>0.3</version>
<executions>
<execution>
<id>iterate</id>
<phase>test</phase>
<goals>
<goal>iterator</goal>
</goals>
<configuration>
<folder>target/generated/classes</folder>
<pluginExecutors>
<pluginExecutor>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.19.1</version>
</plugin>
<goal>test</goal>
<configuration>
<classesDirectory>target/generated/classes/#item#</classesDirectory>
<reportsDirectory>target/generated/reports/#item#</reportsDirectory>
</configuration>
</pluginExecutor>
</pluginExecutors>
</configuration>
</execution>
</executions>
</plugin>
I'm working on a mixed java and kotlin project by using maven.
The problem I'm facing right now is, maven-compiler-plugin runs before compiling kotlin-maven-plugin.
[INFO] --- maven-compiler-plugin:3.0:compile (default-compile) #annotation ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 11 source files to /Users/hannes/workspace/tikxml/annotation/target/classes
[INFO] --- kotlin-maven-plugin:1.0.0-beta-4583:compile (compile) # annotation
[INFO] Kotlin Compiler version 1.0.0-beta-4583
In my java source code I'm referencing classes written in kotlin. But javac runs before kotlinc. Hence, maven interrupts with compiler errors.
My pom (parent pom, I use submodules) looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.sonatype.oss</groupId>
<artifactId>oss-parent</artifactId>
<version>7</version>
</parent>
...
<modules>
<module>core</module>
<module>annotation</module>
<module>processor</module>
</modules>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.7</java.version>
<kotlin.version>1.0.0-beta-4583</kotlin.version>
</properties>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.0</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-plugin</artifactId>
<version>${kotlin.version}</version>
<executions>
<execution>
<id>compile</id>
<phase>compile</phase>
<goals>
<goal>compile</goal>
</goals>
<configuration>
<sourceDirs>
<source>src/main/java</source>
</sourceDirs>
</configuration>
</execution>
<execution>
<id>test-compile</id>
<phase>test-compile</phase>
<goals>
<goal>test-compile</goal>
</goals>
<configuration>
<sourceDirs>
<source>src/test/java</source>
</sourceDirs>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
The Kotlin documentation on Using Maven suggests explicitly binding the kotlin-maven-plugin execution to the process-sources phase. Since maven-compiler-plugin is bound to the compile phase, binding kotlin-maven-plugin to the process-sources phase makes it run first.
<plugin>
<artifactId>kotlin-maven-plugin</artifactId>
<groupId>org.jetbrains.kotlin</groupId>
<version>${kotlin.version}</version>
<executions>
<execution>
<id>compile</id>
<phase>process-sources</phase>
<goals> <goal>compile</goal> </goals>
</execution>
<execution>
<id>test-compile</id>
<phase>process-test-sources</phase>
<goals> <goal>test-compile</goal> </goals>
</execution>
</executions>
</plugin>
Although it's more verbose, you can compile both Java and Kotlin sources in the compile phase with the following configuration:
<plugin>
<artifactId>kotlin-maven-plugin</artifactId>
<groupId>org.jetbrains.kotlin</groupId>
<version>${kotlin.version}</version>
<executions>
<execution>
<id>kotlin-compile</id>
<phase>compile</phase>
<goals>
<goal>compile</goal>
</goals>
</execution>
<execution>
<id>kotlin-test-compile</id>
<phase>test-compile</phase>
<goals>
<goal>test-compile</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5</version>
<executions>
<execution>
<id>default-compile</id>
<phase>none</phase>
</execution>
<execution>
<id>default-testCompile</id>
<phase>none</phase>
</execution>
<execution>
<id>java-compile</id>
<phase>compile</phase>
<goals>
<goal>compile</goal>
</goals>
</execution>
<execution>
<id>java-test-compile</id>
<phase>test-compile</phase>
<goals>
<goal>testCompile</goal>
</goals>
</execution>
</executions>
</plugin>
Normally, plugins are executed in the order they are declared in the POM, but the executions of default-compile and default-testCompile are special because they're built-in, so they always go first. The above configuration gets around that by disabling the default compile executions, and declaring maven-compiler-plugin with new compilation executions after the kotlin-maven-plugin. In this way, you can get all compilation to properly occur during the compile phase of the build lifecycle.
A simple but effective solution would be to change the two phases (the <phase> element) applied to the executions of the Kotlin Maven Plugin, from compile to process-sources and from test-compile to process-test-sources.
You want the Kotlin part to be executed before the Java one. Maven by default will invoke the Maven Compiler Plugin as part of the compile phase for source code, and test-compile for test code. Moving the Kotlin part to their previous phases would then make the flow as you wished.
If you wanted the opposite (first Java then Kotlin), then you could have moved the Kotlin part to the next phases (as an example: from compile to process-classes and from test-compile to process-test-classes).
For further details about Maven phases, check the official documentation.
In case you are open to using a different build system, dependent projects are easy to set up with Kobalt:
val p1 = javaProject { ... }
val p2 = kotlinProject(p1) { ... }
This makes project p2 depend on p1. You can also mix Java and Kotlin projects.
I have a Maven project with mixed Java and Scala code. I want to use an auxiliary class located in the scala test folder for Java tests. The file tree is like below, omitting packages:
+ test/
+ java/...
- SomeTest.java
+ scala/...
- Aux.scala
- OtherTest.scala
I want to import code from Aux.scala for use in the SomeTest.java class. It works fine in my IDE, where all folders are marked as test folders. However when building this project in Maven I get an import error from the Java compiler.
How can I configure Maven to use the Scala test code for Java tests?
In order to resolve dependencies on Scala classes in the Java test-compile phase, you have to bind the testCompile goal of the scala-maven-plugin to the process-test-resources phase. That way, the Scala classes are already compiled when you compile the Java test classes.
The following snippet should do the trick:
<plugin>
<groupId>net.alchim31.maven</groupId>
<artifactId>scala-maven-plugin</artifactId>
<version>3.1.4</version>
<executions>
<!-- Run scala compiler in the process-test-resources phase, so that dependencies on
scala classes can be resolved later in the (Java) test-compile phase -->
<execution>
<id>scala-test-compile</id>
<phase>process-test-resources</phase>
<goals>
<goal>testCompile</goal>
</goals>
</execution>
</executions>
</plugin>
The complete build element of my pom.xml for a mixed Java/Scala project looks the following:
<build>
<sourceDirectory>src/main/scala</sourceDirectory>
<testSourceDirectory>src/test/java</testSourceDirectory>
<plugins>
<plugin>
<groupId>net.alchim31.maven</groupId>
<artifactId>scala-maven-plugin</artifactId>
<version>3.1.4</version>
<executions>
<!-- Run scala compiler in the process-test-resources phase, so that dependencies on
scala classes can be resolved later in the (Java) test-compile phase -->
<execution>
<id>scala-test-compile</id>
<phase>process-test-resources</phase>
<goals>
<goal>testCompile</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.18.1</version>
</plugin>
<plugin>
<groupId>org.scalatest</groupId>
<artifactId>scalatest-maven-plugin</artifactId>
<version>1.0</version>
<configuration>
<reportsDirectory>${project.build.directory}/surefire-reports</reportsDirectory>
<stdout>W</stdout> <!-- Skip coloring output -->
</configuration>
<executions>
<execution>
<id>scala-test</id>
<goals>
<goal>test</goal>
</goals>
<configuration>
<suffixes>(?<!(IT|Integration))(Test|Suite|Case)</suffixes>
</configuration>
</execution>
<execution>
<id>integration-test</id>
<phase>integration-test</phase>
<goals>
<goal>test</goal>
</goals>
<configuration>
<suffixes>(IT|Integration)(Test|Suite|Case)</suffixes>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
I want to run the maven compiler plugin in a different phase and with different sourceDirectories and destinationDirectories such that code from directories other than src/main/java and src/test/java can be used.
I thought the solution would look something like the below, where the phase I was linking it to was pre-integration-test. However the properties for testSourceDirectory and testOutputDirectory don't seem to be specified in this way as they are in the section of the POM.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<executions>
<execution>
<id>compile mytests</id>
<goals>
<goal>testCompile</goal>
</goals>
<phase>pre-integration-test</phase>
<configuration>
<testSourceDirectory>${basedir}/src/inttest/java</testSourceDirectory>
<testOutputDirectory>${basedir}/target/inttest-classes</testOutputDirectory>
</configuration>
</execution>
</executions>
</plugin>
Is there a way to get this plug-in to compile different directories in different phases without affecting its default operation?
The source directories are set outside the compiler-plugin inside the <build> element, so this won't work.
You can use the build-helper-maven-plugin's add-source and add-test-source to specify additional source directories for your integration tests, but this will not remove the existing source dirs.
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>1.3</version>
<executions>
<execution>
<id>add-it-source</id>
<phase>pre-integration-test</phase>
<goals>
<goal>add-source</goal>
</goals>
<configuration>
<sources>
<source>${basedir}/src/inttest/java</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
If you bind the add-test-source goal to run just before the testCompile goal, your integration tests will be included. Note you want them to be output to target/test-classes so the surefire plugin will find them.
To handle removal of the standard test sources, I wrote a small plugin to modify the model to remove existing testSource locations before adding the ones for integration tests.
After more research it is apparent this is not actually possible in Maven 2 in the way I want, a hack of some form is necessary to introduce integration tests. While you can add additional directories (as suggested by Rich Seller) there is no plugin to remove the other sources or to compile a directory separately from the main compilation.
The best solution I have found for adding integration tests is to first use the build helper plugin to add the directory inttest directory to be compiled as tests.
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<executions>
<execution>
<id>add-test-source</id>
<phase>generate-sources</phase>
<goals>
<goal>add-test-source</goal>
</goals>
<configuration>
<sources>
<source>src/inttest/java</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
Now in order to get the integration tests to execute on the integration-test phase you need to use excludes and includes to manipulate when they get run as below. This allow any custom parameters you might want (in my case an agent being added via argline).
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<excludes>
<exclude>**/itest/**</exclude>
</excludes>
</configuration>
<executions>
<execution>
<id>inttests</id>
<goals>
<goal>test</goal>
</goals>
<phase>integration-test</phase>
<configuration>
<excludes><exclude>none</exclude></excludes>
<includes>
<include>**/itest/**/*Test.java</include>
</includes>
</configuration>
</execution>
</executions>
</plugin>