Can you set a property to defer test failure?


(gradle) #1

Is there a way I can set up Gradle so that it doesn’t immediately fail if there are test problems, but sets a property so I can fail the build later? Here is my scenario:

I want to use the Cobertura plugin in my build, and I want it to generate a report every time the build runs. The cobertura plugin adds a “cobertura” task that generates the report, and it depends on the test task. The problem is, if any of the tests fail the cobertura task doesn’t run. I can put “test.ignoreFailures=true” to get the cobertura task to run regardless, but then it will continue on after that as if all was well, and it will ultimately report build success, which is not good for a CI environment.

What I’d like to do is have a task that depends on the cobertura task, but would throw an exception if the test task had any failed tests. This would let me generate a coverage report every time, but I can abort the build if a test failed - after the reports were generated. It is similar to the way Ant users use the errorproperty and failure property in the junit task.

Is this something that can be done in Gradle?

Thanks,

Steve


(Peter Niederwieser) #2

You can either use ‘–continue’, or use ‘test.ignoreFailures=true’ and register a test listener that remembers whether tests have failed. A subsequent task would then act on that.


(gradle) #3

Thanks for the info, that did the trick. For those who find this thread later, here is what I added to my build.gradle file.

// When using the cobertura plugin, it defines a cobertura task that depends
// on the test task, and builds the reports.
The problem is that if the tests
// fail, no report is generated.
We can change the test task to ignore
 // failures, but then the build would succeed even if tests failed.
//
// the solution is to check, when the task graph is ready, to see if the
 // cobertura task is set to run.
If it is, we need to register a test listener
// to all the test tasks that sets a property when tests fail, and we need to
// tell the test tasks to ignore failures.
Then we need to append a check to
 // the end of the cobertura task that instructs the build to fail if the test
// failure property is set.
project.gradle.taskGraph.whenReady { taskGraph ->
    if ( taskGraph.allTasks.find { it.name == "cobertura" } != null) {
        project.tasks.withType(Test).each { Test test ->
            test.ignoreFailures=true
            test.afterSuite { td, tr ->
                if ( td.getParent() == null ) {
                    project.ext.testFailures=tr.getFailedTestCount()
                }
            }
        }
        project.tasks.getByName("cobertura") {
            doLast {
                if ( testFailures ) {
                   throw new Exception("There were ${testFailures} test failures")
                  }
            }
        }
}

So now, if I do a “gradle cobertura”, I’ll get a coverage report, then a failure of tests had failed in any test tasks. If I do a “gradle test”, I’ll get tests without the coverage report, and the build will still fail if there are test failures.