user8681
user8681

Reputation:

Run unit tests in all projects, even if some fail

I have a multi module Gradle project. I want it to compile and do all other tasks as normal. 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've tried adding

buildscript {
    gradle.startParameter.continueOnFailure = true
}

which works for the tests, but also makes compile continue if something fails. That's not OK.

Can I configure Gradle to continue, only for test tasks?

Upvotes: 5

Views: 3702

Answers (2)

Manushin Igor
Manushin Igor

Reputation: 3689

I changed @LazerBanana answer to cancel next tasks after test fail.

Usually all publishing starts after all tests (as an example - Artifactory plugin does this). So, instead of build failure, it is better to add global task, which will be between tests and publishing (or run). So, your task sequence should be like this:

  1. Compile each project
  2. Test each project
  3. Collect test results on the all project and fail the build
  4. Publish artifacts, notify user, etc.

Additional items:

  1. I avoid using Ant Fail. There is GradleException for this purpose
  2. testCheck task executes all code in 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)

Upvotes: 3

LazerBanana
LazerBanana

Reputation: 7221

Try something like this in main build.gradle and let me know, I have tested that with a small 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 ! ")
    }

}

Upvotes: 1

Related Questions