Run unit tests on all projects, even if some failures
I have a project with multiple Gradle modules. I want it to compile and do all other tasks as usual. But for unit tests, I want it to run all of them, instead of stopping as soon as one test in an early project fails.
I tried adding
buildscript {
gradle.startParameter.continueOnFailure = true
}
which works for tests, but also makes compilation continue if something fails. It is not normal.
Can I configure Gradle to continue, for test tasks only?
source to share
Try something like this in the main one build.gradle
and let me know, I tested this with a little pmultiproject and seems to do what you need.
ext.testFailures = 0 //set a global variable to hold a number of failures
gradle.taskGraph.whenReady { taskGraph ->
taskGraph.allTasks.each { task -> //get all tasks
if (task.name == "test") { //filter it to test tasks only
task.ignoreFailures = true //keepgoing if it fails
task.afterSuite { desc, result ->
if (desc.getParent() == null) {
ext.testFailures += result.getFailedTestCount() //count failures
}
}
}
}
}
gradle.buildFinished { //when it finishes check if there are any failures and blow up
if (ext.testFailures > 0) {
ant.fail("The build finished but ${ext.testFailures} tests failed - blowing up the build ! ")
}
}
source to share
I modified @ LazerBanana's answer to cancel the following tasks after the test completes.
Publishing usually starts after all tests (Artifactory plugin as an example). So instead of failing the build, it is better to add a global task that will run between tests and publish (or run). So your task sequence should be like this:
- Compile each project
- Check each project
- Collect test results from the whole project and don't build
- Publish artifacts, notify user, etc.
Additional elements:
- I avoid using Ant Fail. There is a GradleException for this purpose.
- The testCheck task runs all the code in the doLast section as recommended by gradle
code:
ext.testFailures = 0 //set a global variable to hold a number of failures
task testCheck() {
doLast {
if (testFailures > 0) {
message = "The build finished but ${testFailures} tests failed - blowing up the build ! "
throw new GradleException(message)
}
}
}
gradle.taskGraph.whenReady { taskGraph ->
taskGraph.allTasks.each { task -> //get all tasks
if (task.name == "test") { //filter it to test tasks only
task.ignoreFailures = true //keepgoing if it fails
task.afterSuite { desc, result ->
if (desc.getParent() == null) {
ext.testFailures += result.getFailedTestCount() //count failures
}
}
testCheck.dependsOn(task)
}
}
}
// add below tasks, which are usually executed after tests
// as en example, here are build and publishing, to prevent artifacts upload
// after failed tests
// so, you can execute the following line on your build server:
// gradle artifactoryPublish
// So, after failed tests publishing will cancelled
build.dependsOn(testCheck)
artifactoryPublish.dependsOn(testCheck)
distZip.dependsOn(testCheck)
configureDist.dependsOn(testCheck)
source to share