Mastering Maven: Failing Faster With Failing Tests
Maven uses the Surefire plugin to run unit tests and the Failsafe plugin to run integration tests.
The default behaviour of Maven is to run all tests and show a summary at the end.
The summary shows how many tests have run and how many failures, errors and skipped tests happened.
So every time when you run mvn test or mvn verify all tests will be executed, even when tests are failing.
You can speed up your build by stop running tests once a test fails.
You must use the Java system properties surefire.skipAfterFailureCount and failsafe.skipAfterFailureCount to make sure Maven will skip running any tests after a test failure has occurred.
You can specify a number with the parameter to set how many tests should fail before other tests are skipped.
It is possible use these parameters in the plugin configuration in your pom.xml as well.
In the following example you see first the results of a default mvn test run where two failures happen in the test set:
> mvn test
...
[INFO] Results:
[INFO]
[ERROR] Failures:
[ERROR] HelloServiceTest.helloWithName:28
expected: "Hello mrhaki!"
but was: "Hello mrhaki"
[ERROR] HelloServiceTest.helloWithWorld:21
expected: "Hello World!"
but was: "Hello World"
[INFO]
[ERROR] Tests run: 5, Failures: 2, Errors: 0, Skipped: 0
...
>
By using the Java system properties surefire.skipAfterFailureCount and failsafe.skipAfterFailureCount with the value 1 you can see in the output tests were skipped after the first failure:
> mvn test -Dsurefire.skipAfterFailureCount=1
...
[INFO] Results:
[INFO]
[ERROR] Failures:
[ERROR] HelloServiceTest.helloWithWorld:21
expected: "Hello World!"
but was: "Hello World"
[INFO]
[ERROR] Tests run: 5, Failures: 1, Errors: 0, Skipped: 1
...
>
Notice that tests that have run before the failing test are still executed. So in the previous example some time is saved by skipping a test. In larger codebases the number of skipped tests can be larger and the build will fail faster than running all tests.
But still to fail faster you want to skip all tests except the failing tests.
The order of running tests is by default the location on the file system of the test classes.
So if your failing tests location is one of the last to be executed you are not failing much faster.
But you can change the order of tests that are executed.
In this case we want to have the failing tests run first, so we can work on fixing the test and run the test suite and fail fast this time if the fix is not enough.
With the system properties surefire.runOrder and failsafe.runOrder you can change the ordering of tests.
The value failedFirst will run tests that failed on a previous run first.
In the following example the run order is set to failedFirst:
> mvn test -Dsurefire.skipAfterFailureCount=1 -Dsurefire.runOrder=failedFirst
...
[INFO] Results:
[INFO]
[ERROR] Failures:
[ERROR] HelloServiceTest.helloWithWorld:21
expected: "Hello World!"
but was: "Hello World"
[INFO]
[ERROR] Tests run: 5, Failures: 1, Errors: 0, Skipped: 4
...
>
This time 4 tests are skipped and only the failed test is executed.
Written with Maven 3.9.10.