In what lifecycle point are tests ignored when building? - maven

I am trying to understand the maven build lifecycle when it is regarding to tests:
Let's say I have a project with a class in the src/main folder and another one in the src/test. When I run mvn install, it get's compiled, then tested, then packaged and installed.
Until now I thought that maven would not package the tests in the snapshot, because this is not "production" code. Is this true?
In this case, when does maven ignores the test files?

What you said about the Maven lifecycle is true. The "main" phases include:
compile: in this phase, the maven-compiler-plugin:compile goal is run which compiles the main code of the project.
test-compile: in this phase, the maven-compiler-plugin:testCompile goal is run which compiles the test code of the project.
test: in this phase, the maven-surefire-plugin:test goal is run and all the unit tests are executed.
package: in this phase, the maven-jar-plugin:jar goal is run and creates a JAR of the current project. By default, this JAR will include all classes under target/classes, which contains all the main classes, but not the test classes which are located inside target/test-classes. You could say that it is at this step that Maven ignores the test classes.
install: in this phase, the maven-install-plugin:install will install the main artifact, and every attached artifact, into your local repository.
To answer more precisely, it's not that Maven ignores the test classes, it is that by default, the packaging process only considers the main classes. But you can configure it to also package the test classes with the maven-jar-plugin:test-jar goal inside another attached artifact.

Related

Generated code is not compiled

I wrote a Mojo that creates a new Java class and puts it in /target/generated-sources/annotations. in addition, I have configured build-helper-maven-plugin to declare that folder as source folder.
The problem is when I do: mvn clean install from CLI it generates the source file but it doesn't compile it.
Note, if I run Maven Install from within Eclipse (using the m2e connector) then it works fine.
What am I missing?
Without an actual plugin definition, we can only speculate.
I can't comment on m2e, I see one obvious difference that you state by yourself: mvn clean install vs mvn install, but from the "bare" maven's standpoint,
here is one possible reason:
Maven has a concept of phases that comprise the lifecycle. An information about phases of default lifecycle is available here
Plugins (more precisely the "goals" of plugins) are something that usually gets attached to a particular phase.
Maven compiler plugin is attached to the compile phase, for example.
So, maybe the plugin that you've developed runs later than the compiler plugin.
Usually, source generation plugins are attached to generate-resources phase.
Its possible to run a full lifecycle in maven, in fact its what people usually do, for example, running mvn test actually means, run all phases of the default lifecycle up-to (including) phase test.
It's also possible however to run a particular plugin goal "directly" without attaching it to the phase. Of course, in this case, its pre-conditions should be met.
For example, mvn surefire:test means that we should invoke the surefire plugin directly. Of course the source code and test code should be compiled beforehand (bytecode has to exist in the target directory)
So I suggest you to run the following series of commands (Adjust if you have tests):
Run mvn clean install on the plugin project to place it to local m2 repo
Run the plugin directly: mvn ::: and check
whether the source is generated in the target folder
Make sure in pom.xml of the project that the source folder are configured correctly
Run mvn compile (phase up-to, including, compile) on pom even without the plugin
After this phase, there will be compiled sources in the target directory. Don't run
clean because it will wipe out all the target directory
This will effectively help to make sure that plugin does the job right

Why 'mvn install' war projects?

My maven project packages a war, which only gets deployed and is itself not a dependency to other projects (in other words is a final deployable).
Questions:
is there any reason to ever run mvn install on that package, which, in addition to mvn package only puts it in the localRepository?
Why should a final deployable be installed if nothing ever depends on it?
For a final deployable artifact indeed there may be no reason to invoke the install phase instead of the package phase: you want to build the .war file and you don't need to install it in your local repository indeed.
However, you may want as an habit to always run integration tests, if any. Looking at the default Maven lifecycle these phases happen after the packaging:
package take the compiled code and package it in its distributable format, such as a JAR.
pre-integration-test perform actions required before integration tests are executed. This may involve things such as setting up the required environment.
integration-test process and deploy the package if necessary into an environment where integration tests can be run.
post-integration-test perform actions required after integration tests have been executed. This may including cleaning up the environment.
verify run any checks to verify the package is valid and meets quality criteria.
install install the package into the local repository, for use as a dependency in other projects locally.
Hence, by invoking install you would make sure to always execute integration tests as well. Indeed a shorter invocation would be
mvn clean verify
Less popular but more effective in these cases.

How tell to maven don't bring test dependencies

I have Maven dependencies with scope test.
I add flag Dmaven.test.skip=true but Maven still brings test dependencies.
Is there a way not to bring test dependencies if I want to build only the production part?
This is how maven works - it First tries to check that ako dependencies are available, no matter their scope. Only then it continues to test phase to find out that tests should not be executed.
A possible workaround is to define your test dependencies in a separate test maven profile, which is not applied when you do not want to run tests. Profiles are resolved before any dependence are downloaded, therefore if test dependencies are not added by the profile to the effective pom, they are not downloaded at all.
the flag -Dmaven.test.skip will only skip compilation and execution of your tests within the project you run.
Its often better to use -DskipTests as this will compile the test classes but not run them. See surefire documentation.
This has nothing to do with dependencies. Those are loaded into the classpath depending on their scope and what plugins require. The surefire plugin requires resolution of scope test as it runs the unit tests.
If there are dependencies of scope test which you do not want to use you need to remove them or exclude them if they come in via transitive dependencies (dependencies of dependencies). You can execute a mvn dependency:tree to figure out why jar are in the project.
If you add some dependencies for test scope, maven will first check if the dependency is available or not then it checks the scope.
You can create a maven profile, add test dependencies under the profile and trigger the profile when -Dmaven.test.skip or -Dmaven.test.skip=true option is not present. In this way you can keep your build command unchanged.
You can check this simple project manage-test-dependencies-in-maven-the-proper-way to understand it better.

Maven reactor and site

I have a multi-module project with a parent pom.xml and several modules where some of the modules depend on each other. In the project directory I can call
mvn test
to run unittests in each module. No problem here. But if I call
mvn site
one of the modules reports
[ERROR] Failed to execute goal on project myModule_C: Could not resolve dependencies
for project org.myModule_C:jar:0.0.1-SNAPSHOT: The following artifacts could not be
resolved: org.myModule_A:jar:0.0.1-SNAPSHOT, org.myModule_B:jar:0.0.1-SNAPSHOT: Failure
to find org.myModule_A:jar:0.0.1-SNAPSHOT in http://artifactory-server:8081/artifactory/repo
was cached in the local repository, resolution will not be reattempted until the update
interval of server has elapsed or updates are forced -> [Help 1]
I think this should not happen since these dependencies are found during "mvn test". Also, they are not in the artifactory-server but part of the parent project. The goal that is mentioned in the ERROR is the goal site. Why does the mvn test succeed (with respect to dependencies it finds) and mvn site does not? Do I have to build the site in a special way - because this is a reactor build?
You should execute the mvn install as least once. Please see further information at the Maven Build Life Cycle and Maven in 5 Minutes.
Here is the overview
Maven Phases
Although hardly a comprehensive list, these are the most common default lifecycle phases executed.
validate: validate the project is correct and all necessary information is available
compile: compile the source code of the project
test: test the compiled source code using a suitable unit testing framework. These tests should not require the code be packaged or deployed
package: take the compiled code and package it in its distributable format, such as a JAR.
integration-test: process and deploy the package if necessary into an environment where integration tests can be run
verify: run any checks to verify the package is valid and meets quality criteria
install: install the package into the local repository, for use as a dependency in other projects locally
deploy: done in an integration or release environment, copies the final package to the remote repository for sharing with other developers and projects.
There are two other Maven lifecycles of note beyond the default list above
They are:
clean: cleans up artifacts created by prior builds
site: generates site documentation for this project
I hope this may help.

How can I atomically run mvn tests (without rebuilding source code)?

I want to run a maven project lifecycle starting, and ending, with the unit tests.
How can I skip recompilation and re-resolution of dependencies and only run the test phase?
If you start maven by calling a phase it will execute all lifecycle phases up to the one you are calling. For example, when calling
mvn test
all the phases before the test lifecycle phase will be execute too: the project will be validated, sources and resources will be generated and processed, sources will be compiled, the same will happen to test sources and resources and finally unit tests will be run.
But you can also call the plugin goal that is bound to a lifecycle phase. In the case of the test phase the bound goal is surefire's test mojo. So you could call
mvn surefire:test
and no other lifecycle phase will be executed.
You can find the goals bound to each phase depending on the package type here.
You can run :
mvn surefire:test
Build your own lifecycle, or run the tests with something besides Maven (Ant, Gradle, your IDE, command-line JUnit runner, ...). That's the kind of restriction you live with when you're using Maven.

Resources