In order to clean up something of a giant mess, I set out to put the code of my tests all in one ordinary java project (all in src/main/java), and then declare that as a <scope>test</scope> dependency in another project, and expect the tests to run.
No such luck. surefire wants to just run the tests that it can see in the sources.
I can see a sadly obvious solution here involving the build-helper-plugin and adding the tests into the test compilation environment as a source directory, but I was hoping to avoid it.
In case anyone is wondering, the reason for all this is that the POM configuration for use of the failsafe plugin to run some integration tests got so complex that I wanted to split out the compiling of the test classes from the running of the tests.
This is now possible with Maven Surefire v2.15. Simply add the following kind of configuration to the surefire plugin:
<build>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.15</version>
<configuration>
<dependenciesToScan>
<dependency>com.group.id:my-artifact</dependency>
<dependency>com.group.id:my-other-artifact</dependency>
</dependenciesToScan>
...
</configuration>
...
</plugin>
...
</build>
You should also declare the actual dependencies in the dependencies section:
<dependencies>
<dependency>
<groupId>com.group.id</groupId>
<artifactId>my-artifact</artifactId>
<type>test-jar</type>
<version>1.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.group.id</groupId>
<artifactId>my-other-artifact</artifactId>
<type>test-jar</type>
<version>1.1</version>
<scope>test</scope>
</dependency>
</dependencies>
No such luck. surefire wants to just run the tests that it can see in the sources.
This is currently not possible out of the box, surefire just looks at classes in target/test-classes:
Re: Surefire not picking up tests from test-jar
Re: maven-surefire-plugin: run unit tests from classes in a jar, not a directory
This is actually logged as SUREFIRE-569 - There should be a way to run unit tests from a dependency jar.
I can see a sadly obvious solution here involving the build-helper-plugin and adding the tests into the test compilation environment as a source directory, but I was hoping to avoid it.
The current workaround is to use dependency:unpack to unpack the jar into target/test-classes before the test phase.
Can't you do it the other way round?
I mean put the code the src/test/java, depend on your main module, and run the tests in your test module?
Related
This should be pretty simple, but I can't the around to it. I need to create an uberjar using 3rd party jars. I've already followed these instructions: Including a non-Mavenized dependency so it works with maven-shade-plugin and added them to the local repository. But now what? Every Maven tutorial/example is kinda shady (pun intended) and I just don't know how to edit the .pom file properly in order to make it work.
Besides, I'm confused about the shade "plugin" overall. I mean, I followed the basic Maven tutorials and it went all fine and dandy. But when I look into the shade plugin page, I can't find it to download, except for the source code. I mean, isn't it a plugin? Shouldn't I download the binaries and install it into Maven somehow?
Sorry about the extreme noobish question but, needless to say, I know squat about Maven.
To create your shaded (uber) jar, you just need to declare the shade plugin in your pom.xml.
With regards to installation of the shade plugin, simply declaring it in the plugins section of your pom.xml is all you need do. Maven plugins are not installed manually, but are automatically downloaded by Maven (if not already downloaded; just like dependencies), stored in your local repository, and used whenever a project needs them.
As to using it, much like other plugins, declare it in your pom.xml by adding a <plugin> element with your configuration needs. This plugin does nothing automatically (some do, some don't) - you have to specify which "goal" to execute (think "method of a class"), and in which "phase" (think "step" of the build process). Unless you have strange needs, specify the "shade" goal in the "package" phase (see below).
For more configuration possibilities, see the shade usage page, and their examples (especially selecting contents for uber jar). Here is a simple example which, when you run mvn package, replaces your original jar in the target/ directory with the uber jar. It only includes the runtime dependencies, not the ones used at test time (notice the <scope> element of the junit dependency, which is not included in the uber jar).
<project>
<groupId>com.sample</groupId>
<artifactId>test</artifactId>
<version>1.0</version>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>1.5</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>com.sample</groupId>
<artifactId>test-core</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
If you have already downloaded the binaries and installed them into your local Maven repository all that remains is to declare them as dependencies in the POM. If the shade plugin is also declared in the POM a simple "mvn install" should generate a standalone JAR in the target directory.
He,
I am having a mixed Java / Groovy eclipse project.
Inside eclipse utilizing the groovy plugin everything compiles just fine. In addition I have set up my project to utilize Maven2. And still everything compiles and runs (tests) just fine within eclipse.
However, compiling the project outside eclipse, i.e. using Maven2 standalone gives me compiler errors! The project is devided into several sub-projects (parent / module). The Maven2 configuration seems to be OK cause some of the modules compile but actually one gives me an compiler error, like:
[ERROR] \Projects\X\rules\src\main\groovy\x\Normalizer.java:[18,25] normalize(java.util.List<java.util.Map<java.lang.String,java.lang.Object>>) in x.
x.util.RuleUtil cannot be applied to (java.util.List<java.util.Map<java.lang.String,?>>)
[ERROR] \Projects\X\rules\src\main\groovy\x\Statistics.java:[70,67] inconvertible types
found : capture#683 of ?
required: java.lang.String
Why is this code compiling within eclipse but not using standalone Maven2?
Thanks in advance,
/nm
The problem that you are facing is a stub generation problem. GMaven creates Java stubs for your Groovy files to compile against the remaining Java files. If your application is completely in Groovy, or there is no referencing from Java classes to Groovy classes, you can remove the <goal>generateStubs</goal> goal.
The Groovy-Eclipse compiler does not require stubs and so you are not seeing this issue inside of Eclipse.
If you do require cross referencing between Groovy and Java, I'd recommend using the groovy-eclipse-compiler plugin for maven. More information is here:
http://contraptionsforprogramming.blogspot.com/2010/09/where-are-all-my-stubs.html
With this, you will be sure that your compilation inside Eclipse and outside works exactly the same.
The Groovy Eclipse plugin uses the version of Groovy presents within the plugin folder of Eclipse (groovy-1.7.5).
Most probably, the version of Groovy referenced in your maven file is different. You can specify it thought in the gmaven-runtime:
<plugin>
<groupId>org.codehaus.gmaven</groupId>
<artifactId>gmaven-plugin</artifactId>
<version>1.3</version>
<configuration>
<providerSelection>1.7</providerSelection>
</configuration>
<dependencies>
<dependency>
<groupId>org.codehaus.gmaven.runtime</groupId>
<artifactId>gmaven-runtime-1.7</artifactId>
<version>1.3</version>
<exclusions>
<exclusion>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy-all</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy-all</artifactId>
<version>1.7.5</version>
</dependency>
</dependencies>
<executions>
<execution>
<goals>
<goal>generateStubs</goal>
<goal>compile</goal>
<!-- <goal>generateTestStubs</goal> -->
<goal>testCompile</goal>
</goals>
</execution>
</executions>
</plugin>
Im a new user in maven. I have few doubts.
I have some BAT files that has to executed via maven
While executing my default commands, I need to echo the status like "Started first task"
When the task gets failed user should get error message popup etc.,
Automatic repository update through maven
Maven calling ant to build *.war
Copying the new created build file(*.war) to local folder with date/time
Auto upload/deploy from build machine to server
Testing particular URLs/products to test the site flow
Sending mail regarding deployment status
Below is my example pom.xml, which trying only (a)
<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>
<groupId>com.example.maven</groupId>
<artifactId>test</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<name>test</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.1.1</version>
<executions>
<execution>
<goals>
<goal>exec</goal>
</goals>
</execution>
</executions>
<!--echo>Starting CVS Update</echo-->
<configuration>
<tasks>
<exec>
<directory>D:\</directory>
<executable>"D:\test.bat"</executable>
<!--failonerror="true" -->
<!-- optional -->
<!--workingDirectory>"cd C:\repo\projects\mcsandbox"</workingDirectory-->
</exec>
</tasks>
</configuration>
</plugin>
</plugins>
</build>
</project>
I guess this is not the expected answer but I don't think that you're on the right path and I don't see the point of using Maven the way you'd like to use it. From your description, my impression is that you aren't really adopting Maven but rather trying to insert something existing into it and, believe me, this isn't the easiest way to get started with Maven:
This is going to add an extra layer of complexity.
This requires a deeper understanding of the way maven works than "just" adopting it.
You're going to fight against the tool (and there are good chances that the tool will win).
This will generate more troubles than benefits.
I don't really know where to start so I'll just try to quickly cover your points first:
I have some BAT files that has to executed via maven
This is possible but this is not really the Maven way (depending on the logic, you should move it to Maven or keep it outside maven), and I don't think this is going to be very robust (might be wrong though). On top of that, this already requires some knowledge of the build lifecycle (where to hook things) and of plugin configuration. And from what I've seen (I do not mean to be rude), you don't have it.
While executing my default commands, I need to echo the status like "Started first task"
This is not how things work with Maven. Maven isn't procedural like Ant, Maven has conventions, Maven is declarative, Maven has a lifecycle.
When the task gets failed user should get error message popup etc.,
User? Popup? Maven is not really targeted at end users, Maven is a developer tool and what you get in case of an error is a message in a console.
Automatic repository update through maven
Do you mean a CVS update? This is not impossible but is usually not Maven's job (it's more a Continuous Integration engine task).
Maven calling ant to build *.war
This is possible using the Maven Antrun Plugin but that's not the spirit and may go against some maven rules (like one artifact per project). Also, Maven will not magically be aware of things built by Ant. Why don't you just stick with Ant?
Copying the new created build file(*.war) to local folder with date/time
Possible. But that's not how things work by default.
Auto upload/deploy from build machine to server
Maven has plugins (e.g. Cargo) that can help at doing this but you have to tell him to.
Testing particular URLs/products to test the site flow
Maven itself won't do that. But it can run (integration) tests doing that.
Sending mail regarding deployment status
That's not maven's responsibility (more a Continuous Integration engine task).
My global feeling is that you are thinking too much Ant oriented and maybe expecting too much from Maven. Maven is different, it doesn't really work the way you described, it doesn't work like Ant. My recommendation would be to either fully migrate to Maven and adopt its philosophy or to stick with your current Ant solution (and maybe consider using the Maven Ant Tasks or Ivy to leverage things such as dependency management, artifact deployment).
See also
How to convert from Ant to Maven (...)
Differences between Ant and Maven
Maven: The Definitive Guide
If you have an existing ant file, what is the best way to convert the project to Maven. I've checked out things like fAnt, but if I'm going to mess with this stuff, I might as well go full-bore for Maven. I expected something to exist that can just start the pom.xml for me based on the existing build.xml, but I haven't found anything yet. Suggestions?
I don't know any good automated way to do such a migration because things may just be too different so I would do it manually, step by step, and keep the existing ant build in parallel of the future new one until the whole migration is done (from both technical and human points of view).
First, refactor the existing Ant build to align it on Maven conventions:
Make things modular: if your existing build is a big monolithic build producing several artifacts from a single source tree, break it down into separate modules, one for each artifact.
Update directory structure: Maven comes with a standard directory layout and, while it is possible to customize this layout (i.e. to configure plugins for another layout), this is not really recommended and is more a source of troubles than benefits. So I'd move existing app sources, configuration files, tests, etc to match Maven's layout (e.g. src/main/java for application sources, etc).
Then, start to create the Maven build:
Create POMs for each module: Create a POM, declare external libraries as Maven dependencies (maybe add them to a corporate repository, using an enterprise repository is a good practice in an enterprise context anyway), add dependencies between modules.
Finalize the multi-modules build: Add parent(s) POM(s) and inheritance/aggregating relationships. Test that there is no regression with the created artifacts.
You could do this work in a separate VCS branch if you don't want to change anything until the work is done and create scripts to move things. And when ready, merge the Maven specific stuff and apply the scripts.
You could run the Ant script from Maven with the maven-antrun-plugin. Your pom.xml would look something like this:
<project>
...
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<dependencies>
<dependency>
<groupId>org.apache.ant</groupId>
<artifactId>ant-nodeps</artifactId>
<version>${ant-nodeps.version}</version>
</dependency>
</dependencies>
<executions>
<execution>
<id>init</id>
<phase>compile</phase>
<configuration>
<tasks>
<!-- Ant code goes here -->
</tasks>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
</build>
</project>
That way you can start to move your dependencies into Maven, and reference them in the Ant script like so
${com.foo.bar:my-lib:jar}
Then just start slowly moving pieces of your Ant into pure Maven stuff.
How can you depend on test code from another module in Maven?
Example, I have 2 modules:
Base
Main
I would like a test case in Main to extend a base test class in Base. Is this possible?
Update: Found an acceptable answer, which involves creating a test jar.
I recommend using type instead of classifier (see also: classifier). It tells Maven a bit more explicitly what you are doing (and I've found that m2eclipse and q4e both like it better).
<dependency>
<groupId>com.myco.app</groupId>
<artifactId>foo</artifactId>
<version>1.0-SNAPSHOT</version>
<type>test-jar</type>
<scope>test</scope>
</dependency>
Thanks for the base module suggestion. However, I'd rather not create a new module for just this purpose.
Found an acceptable answer in the Surefire Maven documentation and a blog. See also "How to create a jar containing test classes".
This creates jar file of code from src/test/java using the jar plugin so that modules with tests can share code.
<project>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<executions>
<execution>
<goals>
<goal>test-jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
In order to use the attached test JAR that was created above you simply specify a dependency on the main artifact with a specified classifier of tests:
<project>
...
<dependencies>
<dependency>
<groupId>com.myco.app</groupId>
<artifactId>foo</artifactId>
<version>1.0-SNAPSHOT</version>
<type>test-jar</type>
<scope>test</scope>
</dependency>
</dependencies>
...
</project>
We solved this by making a maven project with test code as the src/main/java and adding the following dependency to projects:
<dependency>
<groupId>foo</groupId>
<artifactId>test-base</artifactId>
<version>1</version>
<scope>test</scope>
</dependency>
Worked for me for 1 project, but I didn't for another after doing exactly the same steps.
So I debugged:
After mvn clean install I checked /target directory: .jar was there so thats good
Ran mvn dependency:tree on a project which should use those test classes. Noticed that generated jar file with test classes is marked as dependency, so thats good.
Conclusion could be only one - I restarted my Intellj. At first class import was still not visible, but after a minute it started to see it!
Note: I only restarted Intellj, no caches removal etc
Yep ... just include the Base module as a dependency in Main. If you're only inheriting test code, then you can use the scope tag to make sure Maven doesn't include the code in your artifact when deployed. Something like this should work:
<dependency>
<groupId>BaseGroup</groupId>
<artifactId>Base</artifactId>
<version>0.1.0-SNAPSHOT</version>
<scope>test</scope>
</dependency>