The last post of this series has introduced a couple of useful options to manage built modules in a multi-module project. This post focuses on failure. Maven proposes three different way to manage failures in reactor builds: fail-fast (default), fail-at-end and fail-never which will be described in this post.
An example
To illustrate the topic, let’s imagine a simple multi-module project (the same as in the previous post):
- Project is the ‘root’ project, declares the others modules
- Module-A is a simple project
- Module-B depends on Module-A
- Module-C depends on Module-A
- Module-D depends on Module-C
The Module-C contains a failing unit tests:
public class FirstTest { @Test public void a() { System.out.println("A executed..."); org.junit.Assert.fail("oh oh"); } @Test public void b() { System.out.println("B executed..."); // OK }
Depending on the options used to build the complete project (i.e. the reactor build), the result will differ.
Fail-Fast
The first policy is the default one. Fail Fast stops the reactor build after the first failing project. Despite used by default, you can enable this policy with: --fail-fast or just -ff
One our example, the build will stop after Module-C:
------------------------------------------------------- T E S T S ------------------------------------------------------- Running maven.test.FirstTest B executed... A executed... Tests run: 2, Failures: 1, Errors: 0, Skipped: 0, Time elapsed: 0.223 sec <<< FAILURE! Running maven.test.SecondTest C executed... Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.006 sec Results : Failed tests: a(maven.test.FirstTest) Tests run: 3, Failures: 1, Errors: 0, Skipped: 0 [INFO] ------------------------------------------------------------------------ [ERROR] BUILD FAILURE [INFO] ------------------------------------------------------------------------ [INFO] There are test failures.
With this policy, the build is stopped after the first failing module. It gives you the opportunity to fix the issue. This avoids the propagation of the ‘bug’ to others modules. However, it does not necessary fit for big project where the failure may not impact others modules. Moreover, quality builds generally analyzes all modules and shouldn’t be stopped after the first failed tests.
Fail-at-end
The second policy to manage failure is named fail-at-end. To enable this policy, use the --fail-at-end (or just -fae) parameter. This policy fails the build afterward and allows all non-impacted builds to continue. On our project:
mvn clean install --fae => builds Module A, B, C (failed), skip D
produces
[INFO] [INFO] [INFO] ------------------------------------------------------------------------ [INFO] Reactor Summary: [INFO] ------------------------------------------------------------------------ [INFO] Module A .............................................. SUCCESS [2.849s] [INFO] Module B .............................................. SUCCESS [0.070s] [INFO] Module C .............................................. FAILED [9.474s] [INFO] Module D .............................................. SKIPPED (dependency build failed or was skipped) [INFO] Reactor ............................................... SUCCESS [0.948s] [INFO] ------------------------------------------------------------------------ [INFO] Error for project: Module C (during install) [INFO] ------------------------------------------------------------------------ [INFO] There are test failures. Please refer to /Users/clement/workspaces/experiments/Project/module-C/target/surefire-reports for the individual test results.
This policy allows all non-impacted builds to continue. However, D depends on C, so as C failed, D is skipped. The global build is also considered as failed. This option avoid issue propagation, which is an interesting feature.
This option is useful to try to compile a maximum of modules. If the project contains independent modules, this option is really interesting (especially if we are interested by modules built after the initial failures). A last detail to know about this option, it does not only support test failures, but all project failures (wrong configuration, missing dependencies, etc.). However, for quality builds, or for builds with post-actions, this option is not enough, that’s why there is a third option.
Fail-Never
This last option must be used carefully, but can be useful. The build never fails, regardless of the project result. All failures are ignore, the build just continues. On your project:
mvn clean install --fail-never (or just --fn)
produces:
[INFO] [INFO] ------------------------------------------------------------------------ [INFO] Reactor Summary: [INFO] ------------------------------------------------------------------------ [INFO] Module A .............................................. SUCCESS [2.583s] [INFO] Module B .............................................. SUCCESS [0.086s] [INFO] Module C .............................................. FAILED [1.598s] [INFO] Module D .............................................. SUCCESS [0.051s] [INFO] Reactor ............................................... SUCCESS [0.921s] [INFO] ------------------------------------------------------------------------ [INFO] Error for project: Module C (during install) [INFO] ------------------------------------------------------------------------ [INFO] There are test failures. Please refer to /Users/clement/workspaces/experiments/Project/module-C/target/surefire-reports for the individual test results. [INFO] ------------------------------------------------------------------------ [INFO] For more information, run Maven with the -e switch [INFO] ------------------------------------------------------------------------ [INFO] + Ignoring failures [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESSFUL [INFO] ------------------------------------------------------------------------ [INFO] Total time: 5 seconds [INFO] Finished at: Sun May 09 10:43:41 CEST 2010 [INFO] Final Memory: 31M/79M [INFO] ------------------------------------------------------------------------
Module C failed, D is not skipped, and the global build is successful.
This policy is generally used for quality builds that must be executed on all modules. Build with post-actions may also be interested. However, I don’t recommend this options for regular builds (e.g., on the developer machine).
great, to avoid a bug in maven 2.2.1 we need to do a first clean install which fails and then do another build.
Hello, thank you for this post. However, I have a question. I am not sure about the behaviour of the fail-at-end.
You say, that module D is skipped:
mvn clean install –fae => builds Module A, B, C (failed), skip D
But I would expect that D build will be executed as well, but the total build result will be failed?