Difference between the main and the test folder in Maven - maven

I am a bit confused on the difference between the use of the folder main and the folder test in Maven. As of now, I just copy and paste my source code in both of them and it works fine. I don't get what the point of having another folder with exactly the same thing as the main folder is? Can someone please explain this to me.
Also:
What is the difference between install and compile.
So for this command: mvn archetype:generate, is generate the goal? then what is archetype?
Thanks

The main folder contains your application code and resources, and the test folder contains, well, test code and resources. So don't copy your application code there, but only the tests. The test sources are then automatically added to the classpath in the test phases.
For the difference between install and compile have a look at https://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html. Basically install also contains compile and a lot more goals (like execution of tests, packaging, installing into local repository.
generate would be the goal, correct. archetype is the short form for maven-archetype-plugin and means the plugin, which contains the goal. By default plugins with the name pattern maven-*-plugin or *-maven-plugin can be shortened that way.

Separation between src and test folders is a standard practice where same package structure under both guarantees your com.some.Class finds its way and it's visible when com.some.ClassTest unit test runs.
Difference between install and compile. Read the documentation around the Maven lifecycle. Essentially everytime you are invoking one build phase, every other build phase defined before it in the lifecycle gets called in the defined order.
Documentation about what is Archetype

Related

Maven: How to manage test code module dependencies

We've migrated an ant project (codename one) to a maven project which happened through a migration tool. Unfortunately there is still a problem. Somehow, the test source directory (set via testSourceDirectory in pom.xml) becomes part of the wrong module (it is at least shown so in the project view of IntelliJ IDEA). Therefore the test source code is missing neccessary core dependencies. The core code (actual implementation) is in the "common" module. Even though the test code is located (in IntelliJ) under the "common" module, it is itself marked as being part of the "cn1libs" module. We have no idea, how the ide or maven concludes this from the pom config.
snippet from the pom:
<testSourceDirectory>${project.basedir}/common/src/test/java</testSourceDirectory>
the dependencies in the test sources can't get resolved
How can we fix this?
Sometimes IntelliJ will give you erroneous labels like this if there is more than one module that references that directory in their pom file. Check your cn1libs/pom.xml file and make sure that it doesn't have <testSourceDirectory> specified anywhere. Its packaging type should also be pom.
Codename One projects are set up to do unit tests using the Codename One test runner. It uses its own "test" goal. You are importing junit's Test class which may be problematic here unless you really know what you are doing. E.g. The Codename One testrunner will set up the test environment and run the tests in a simulated environment. Junit will just run them raw.
If you need to add test dependencies, however, you should be able to just add them in the dependencies section of the common/pom.xml file, just make sure you set the dependency scope to "test".

Maven module dependency source instead of repository jars

I have a multi-module project, i.e.
parent
module1
module2
In one dev cycle, I added a class mod1.A to module1. Class mod2.B in module2 depends on it.
I do not have the artifacts in my local .m2/repository. Running this:
$ cd prj/module2
$ mvn -o exec:java -Dexec.mainClass=mod2.B
results in an error along the lines of:
The following artifacts could not be resolved: com.example:module1:jar:1.0-SNAPSHOT
After I install the artifacts via mvn install while in the prj folder, it all works as expected.
However, this presents an issue in at least two ways:
I have to go through the slower install phase instead of the faster compile phase
I have two versions of the same project and conflicting modifications in these. I cannot run the same Java class with their respective modifications, only the currently installed modifications, considering they are both the same SNAPSHOT version
There are workaround for both (skip parts of the build for the first, different snapshot versions for the second), but they are far from usable in practice.
Is there a way to make maven use the local modules, instead of using artifacts from local maven repository?
If I understand your question correctly, it seems like you are living a bit outside the norm here: you have two local "copies" of the project with different modifications, that you want to work with alternately when running "exec:java". And Maven is getting in your way: it expects your local .m2 repository area to be in play, but the version strings in each copy are the same, so you end up with the changes interfering among the copies.
To me, it sounds like what you are trying to do is to test your changes. I suggest you just write an actual JUnit or TestNG test in module2 that tests what you want (it can just call mod2.B Main if you want). Then, from your chosen project directory, you can run mvn test -Dtest=MyTestName. It won't "install" anything and it will find the dependencies the way you want it to.
Otherwise, I can see three options.
Change the version string locally in one of the copies (mvn versions:set -DnewVersion=B-SNAPSHOT can do this for you). That way any "installed" jars from your work on that copy will not be considered by the other copy, and vice-versa. You refer to this as being "far from usable" ... I think it should be fine? These are different versions of the project! They should have different version strings! I strongly recommend this option out of the three. (You can do mvn versions:revert when done if you used :set, or you can rely on version control to undo the change.)
Select a different local repository used by Maven when working on one of the projects, with a command-line flag as per https://stackoverflow.com/a/7071791/58549. I don't really think this is a good solution, since you would have to be very careful about using the right flags every time with both projects. Also you'd end up having to re-download Maven plugins and any other dependencies into your new local repository anyway, which is kind of a waste of time.
Try to avoid using any local repository at all. You seem to be trying to make this option work. I don't think this is a great approach either; you're fighting against Maven's expectations, and it limits your flexibility a lot. Maven will indeed find dependencies from the "reactor" (i.e., the executing mvn process) first, but this means all of the required modules must be available in the reactor to be found, which means you can only run mvn at the top level. So if instead you want to just do "mvn exec:java" inside a single module, mvn needs to find that module's dependencies somewhere ... and that's what the local repo is generally used for.
If you're dead set on going with option 3 (instead of option 1), then I suggest you follow the comments on your question and create a profile that runs your exec selectively against module2 and binds it to a lifecycle phase. But this is in practice very close to just wrapping it with a test.
For IntelliJ users:
I solved this problem using IntelliJ's Run configuration. It has the options Resolve workspace artifacts and Add before launch task -> Build. See this picture for clarification:
Run configuration example
The whole point of modules in Maven is to create decoupling between them. You either build each module independently, so that you can work on one module without touching the other, or include both modules as sub-modules in the parent pom and build the parent, which will resolve dependencies between its sub-modules and trigger their builds.
It looks like you have two options here:
Review the structure of your project. Do you really need to split it into two separate modules, if you change code in both of them simultaneously?
Import the project into a Maven-aware IDE (IntelliJ IDEA is very good at working with Maven), and let the IDE handle the compilation. Once finished and stabilized the code-base, build normally with Maven.

Testing in Maven

So I have a project in Maven, with the tree structure it made and the code completed.
Now Im in the test phase and supposedly (if I am not wrong) I have to use the AppTest.java in the test branch of the project.
The thing is that the classes I need to test are in the "main" branch of the project.
How do I import them so that the test can be performed?
EDIT:
Yes, with branch I wasnt referring to anything version control related but about the location in the folders maven autogenerates (given the tree view of the folders used by Eclipse).
ANSWER:
As Aaron Digulla said, I could import them as usual.
It was enough with "import domain.NameOfClass;"
It complained about not being able to autocomplete the route when I typed the dot, but ignoring it was the way to go since it ended up working.
Maven took care of that.
Just import them as usual. When running the tests, Maven will create a classpath which will make everything in src/main/java visible to the test classes.

Maven deleted class still in jar if mvn clean not run

In an effort to speed up my maven build time, I want to run mvn install and not mvn clean install.
If I do this, and a source file was removed (in VCS and I got this change after updating my copy), maven will still pack the old file (since it's still under the target folder).
I'm aware of this thread and others similar, but I'm not satisfied with the end result.
I assumed that maven is "smart" enough to pick up only changes and do a real incremental build, but this behavior breaks this assumption...
Does anyone have an idea on how to enjoy a true incremental build with maven without using the clean life-cycle?
Maven runs through it's lifecycle, running external tools through plugins at various points in the process. You can choose where this process begins, and the recommended starting point is clean. We recommend this because maven knows nothing about your source-code -- it doesn't even know whether it's java or C++ -- and it doesn't have to. It just knows that it should invoke the configured compiler (javac for example) on the configured source directory as soon as it reaches the compile step of the lifecycle.
Your compiler knows about source, so if something is to blame here, blame the compiler. However, most compilers will not delete a compiled artifact just because a source file has been removed, because it doesn't know that this artifact isn't going to be linked (referenced) later -- as far as the compiler is concerned, it's only interested in artifacts relating to source files. This is probably the only tool that looks at your source (except maybe some static code analysis tools and perhaps some documentation tools such as site and javadoc).
Maven will proceed after compilation to run your tests, and if they pass it'll enter into the packaging step. Packaging is again an external tool (jar for example), configured through a plugin. In the case of jars or wars, this takes the contents of the target directory and zips them up into a jar or war according to the configured instructions. Again, there is no part of this that needs to know if a file was removed from the source or not -- in fact, it doesn't even look at the source at this point, so how would it know that a file was removed.
My point is, you're assuming too much of your development environment. It has no way of knowing that a file in a target directory is unneeded, unless you go to great lengths to tell it that this is so. That's why there is a clean step in the first place.
As an aside, clean shouldn't be taking a lot of time. If it is, perhaps you should refactor your project into more modules.

How do I run Selenium RC junit tests with Maven outside normal lifecycle?

I have a Maven project that is a set of a Selenium 2 tests that run using JUnit. In other words the only thing in the whole project is JUnit testcases and they all reside in the normal source directory i.e. src/main/java since they are the main source files in the project.
I want to be able to run these same tests using Maven, but since these tests are not actual unit tests or integration tests within the project (they are not testing themselves, they are testing a web app somewhere else), I don't want them to run during the normal build lifecycle. However I still would like to be able to define the test phases/goals within the POM file.
At this point I sort of understand the way the surefire plugin works, I just don't know how to de-couple the executions from the build. I would like all my new executions to be stand-alone so that I can simply run them by doing something like: mvn run-webtests and have the run-webtests phase be something completely different from the compile and package goals of my project.
So I guess I have two overall questions:
1.) Am I on the right track or is there some better way to think of this problem?
2.) What is it that I need to do next to make this work? Create a custom phase? Create a custom goal?
Sorry for asking such a seemingly basic question, but I wasn't able to find any examples of someone doing anything like this.
I think you're on the right track. It's just that Maven is unfortunately lacking in flexibility in some areas. Usually stuff can be made to fit in, but sometimes it can be a real pain. I think the simplest way to make this work is to use a different naming convention for your selenium tests and make sure those are excluded from your "normal" test runs. Then define a profile where you configure the surefire plugin to include your selenium tests and exclude the others. Then to run the selenium tests, you could just
mvn test -P selenium-tests
The only ways that you can set it up so that you could run mvn run-webtests, are
Define a custom lifecycle where "run-webtests" is a phase in the lifecycle, or
Write a plugin, though executing a plugin always has a ':' in it, so it would be more like mvn myplugin:run-webtests.
Those are both more work and harder to maintain than a simple profile in the pom.

Resources