Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Execute gradle task after test

Tags:

gradle

After executing test task in Gradle build I want to always execute additional task which should have access to test result. Something like:

task('afterTest') {
    doLast {
        if (testSuccessful) {
            //
        } else {
            //
        }
    }
}
like image 810
anlar Avatar asked Jan 27 '23 23:01

anlar


2 Answers

There are two parts in your question: 1) make a custom task executed always after test task is executed, 2) make the test "result" available in this custom task.

1) First part is very simple, you just have to use the dedicated Task.finalizedBy method to create a "finalized by" dependency between test task and your custom task. (see Finalizer tasks)

2) Second part is a bit tricky, as there is no simple way provided by Gradle, as far as I know, to get the "result" (SUCCESS or FAILURE) of test task. But you could use API exposed by the Test Task to store the number of test in error into a variable and test this counter in your custom task : here is a working example:

ext{
    // counter of test cases in error
    nbTestOnError = 0
}

test {
    // use "afterTest" hook to increment nbTestOnError   counter
    afterTest {  desc ,  result  ->
        if (result.getResultType().equals(TestResult.ResultType.FAILURE)){
            nbTestOnError++
        }
    }
}

task('afterTest') {
    doLast {
        // implement your logic depending on counter value
        if (nbTestOnError > 0) {
            // do something if test failed
        } else{
            // do something when all tests passed
        }
    }
}

// create "finalized by" dependency
test.finalizedBy afterTest

EDIT : based on important remark in comment from @lance-java : in order to support up-to-date check , you could configure your custom task to be "skipped" if test task is not executed. A simple way would be to use Task upToDateWhen feature (see here) :

task('afterTest') {
    // consider this task "UP TO DATE" if `test` task did not execute
    outputs.upToDateWhen {
        !test.didWork
    }
    doLast {
    //...
    }
}
like image 144
M.Ricciuti Avatar answered Feb 06 '23 15:02

M.Ricciuti


As I said in the other thread, it's best to use the file system to pass values from one task to another. This way the value will be available even if the test task was up to date and skipped. Eg:

test {
    outputs.file "$buildDir/test.properties"
    ext.errorCount = 0
    afterTest {  desc ,  result  ->
        if (result.resultType.name() == "FAILURE") {
            errorCount++
        }
    }
    doLast {
        file("$buildDir/test.properties").text = "errorCount=$errorCount" 
    } 
    finalizedBy 'afterTest' 
    ignoreFailures = true
}
task afterTest {
    dependsOn 'test' 
    inputs.file "$buildDir/test.properties"
    doLast {
        def props = new Properties() 
        props.load(file("$buildDir/test.properties")) 
        def errorCount = Integer.parseInt(props['errorCount'])
        if (errorCount) {
           // doStuff
           throw new TaskExecutionException("$errorCount tests failed") 
        } 
    } 
} 
like image 21
lance-java Avatar answered Feb 06 '23 15:02

lance-java