Gradle returns exit code as 0 though one of its tasks failed

Viewed 1399

Assume I run gradle tasks as below:
./gradlew cleanTest task1 task2 --info --rerun-task
Here if task1 fails and task2 passes, the exit code for this run is still 0. I want it to return non zero if any of the tasks fails.

These are the task added to my build.gradle file

task task1(type: Test) {
    maxParallelForks = 1
    ignoreFailures true
    testLogging {
        events 'started', 'passed', 'skipped', 'failed'
        exceptionFormat "full"
        showStandardStreams = true

        afterSuite { desc, result ->
            if (!desc.parent) { // will match the outermost suite
                println "RESULT: ${result.resultType} \n" +
                        "TOTAL TESTS: ${result.testCount}, " +
                        "SUCCESS: ${result.successfulTestCount}, " +
                        "FAILED: ${result.failedTestCount}, " +
                        "SKIPPED: ${result.skippedTestCount}"
                finalResult = "${result.resultType}"
                failedTest = "${result.failedTestCount}"
            }
        }
    }
    include "org/company/proj/test/Task1/Task1Test.class"
}

task task2(type: Test) {
    maxParallelForks = 1
    ignoreFailures true
    testLogging {
        events 'started', 'passed', 'skipped', 'failed'
        exceptionFormat "full"
        showStandardStreams = true

        afterSuite { desc, result ->
            if (!desc.parent) { // will match the outermost suite
                println "RESULT: ${result.resultType} \n" +
                        "TOTAL TESTS: ${result.testCount}, " +
                        "SUCCESS: ${result.successfulTestCount}, " +
                        "FAILED: ${result.failedTestCount}, " +
                        "SKIPPED: ${result.skippedTestCount}"
                finalResult = "${result.resultType}"
                failedTest = "${result.failedTestCount}"
            }
        }
    }
    include "org/company/proj/test/Task2/Task2Test.class"
}```
1 Answers

From the discussion I gather that ignoreFailures and failFast on the test task do not meet your requirements, right? I could see a use-case where you want to make sure that both test tasks are actually executed, even if the first task has failed tests, but at the same time you want the build to fail in the end when there are failed test cases in any test task.

First of all you might want to think about this. Usually, the intention is to save execution time on the server (or locally) by failing and aborting the build as soon as possible.

However, if you really want to build something that meets your requirements, you gave all the details for that already: You could add a project variable that stores the result of the tests and create an additional task that checks that property and fails if there were failed tests.

ext {
    failedTests = false
}

task test1(type: Test) {
    ignoreFailures true
    afterSuite { desc, result ->
        if (result.failedTestCount > 0) {
            failedTests = true
        }
    }
}

task test2(type: Test) {
    ignoreFailures true
    afterSuite { desc, result ->
        if (result.failedTestCount > 0) {
            failedTests = true
        }
    }
}

task verifyTestResults() {
    //dependsOn("test1", "test2")    // static naming of test tasks
    dependsOn tasks.withType(Test)   // dynamically depend on all test tasks
    doLast {
        if(failedTests) {
            throw new GradleException("There were failing tests!")
        }
    }
}

Now, you only need to call gradlew verifyTestResults.

Related