Gradle incremental builds allow for continuous testing, which is awesome. While appreciating a feature rich IDE, for continuous testing I prefer to keep it simple and run tests directly on the console:

gradle test --continuous

Continuous testing should answer below questions as quickly as possible

  • Has something failed?
  • Why has it failed?

Having many tests in the continuous run is spilling out lots of unhelpful logs for tests that completed successfully.

It seems like a simple request, yet by default there is no way to obtain both a detailed log (i.e. sql expressions) but only for the interesting (failed) part. One could limit the scope by running only specific tests:

gradle test --tests "myTest*" --continuous

…this however requires to constantly change the test filter expression and might also leave out important tests. Eventually the entire test chain would have to be executed anyways.

Luckily Gradle makes it very easy to write custom tasks with Groovy or Kotlin and I found a very pragmatic solution for my problem:

// build.gradle
project.test {
        def outputCache = new LinkedList<String>()

        beforeTest {TestDescriptor testDescriptor -> outputCache.clear() }

        onOutput {TestDescriptor testDescriptor, TestOutputEvent testOutputEvent ->
            outputCache.add(testOutputEvent.getMessage())
            while (outputCache.size() > 1000) outputCache.remove() // drop oldest lines
        }

        afterTest { TestDescriptor testDescriptor, TestResult testResult ->
            if (testResult.resultType == TestResult.ResultType.FAILURE && outputCache.size() > 0) {
                println()
                println(" Output of ${testDescriptor.className}.${testDescriptor.name}:")
                outputCache.each { print("> $it") }
            }
        }
}
tasks.named('test') {
        useJUnitPlatform()
        testLogging {

                events "passed", "failed"
                exceptionFormat = 'full'
                afterSuite { desc, result -> if (!desc.parent) println "Results: ${result.resultType} (${result.testCount} tests, ${result.successfulTestCount} successes, ${result.failedTestCount} failures, ${result.skippedTestCount} skipped)" }
        }