Why do my Gradle tests run repeatedly?

2019-07-19 02:46发布

问题:

I have a pretty standard Gradle build that's building a Java project.

When I run it for the first time, it compiles everything and runs the tests. When I run it a second time without changing any files, it runs the tests again.

According to this thread, Gradle is supposed to be lazy by defaut and not bother running tests if nothing has changed. Has the default behaviour here been changed?

EDIT:

If I run gradle test repeatedly, the tests only run the first time and are subsequently skipped. However, if I run gradle build repeatedly, the tests get re-run every time, even though all other tasks are marked as up-to-date.

回答1:

the gradle uptodate check logs on info level why a task is not considered to be up-to-date. please rerun the "gradle build -i" to run with info logging at check the logging output.

cheers, René



回答2:

OK, so I got the answer thanks to Rene prompting me to look at the '-i' output...

I actually have 2 test tasks: the 'test' one from the Java plugin, and my own 'integrationTest' one. I didn't mention this in the question because I didn't think it was relevant.

It turns out that these tasks are writing their output (reports, etc.) to the same directory, so Gradle's task-based input and output tracking was thinking that something had changed, and re-running the tests.

So the next question (which I will ask separately) becomes: how do I cleanly (and with minimal Groovy/Gradle code) completely separate two instances of the test task.



回答3:

You need to create test tasks in your build.gradle and then call those specific tasks to run a specific set of tests. Here is an example that will filter out classes so that they don't get run twice (such as when running a suite and then re-running its child classes independently):

tasks.withType(Test) {
    jvmArgs '-Xms128m', '-Xmx1024m', '-XX:MaxPermSize=128m'
    maxParallelForks = 4  // this runs tests parallel if more than one class
    testLogging {
        exceptionFormat "full"
        events "started", "passed", "skipped", "failed", "standardOut", "standardError"
        displayGranularity = 0
    }   
}
task runAllTests(type: Test) {
    include '**/AllTests.class'
    testReportDir = file("${reporting.baseDir}/AllTests")
    testResultsDir = file("${buildDir}/test-results/AllTests")
}
task runSkipSuite(type: Test) {
    include '**/Test*.class'
    testReportDir = file("${reporting.baseDir}/Tests")
    testResultsDir = file("${buildDir}/test-results/Tests")
}

Also, concerning your build question. The "build" task includes a clean step which is cleaning tests from your build directory. Otherwise the execution thinks the tests have already been ran.



标签: gradle