Looking for a way to force a successful Test task to run again on subsequent runs without performing a clean

I have several tasks of Type Test that I have added to my build, like this:

// dynamically build up a testng task for every testng suite found.
// for example testng-unit-test-suite will become a task called runTestSuiteUnit
def testngSuiteTree = fileTree('test/resources/conf/testng').include('testng-*-test-suite.xml')
testngSuiteTree.each { file ->
    def matcher = file.name =~ /testng-(.*)-test-suite.xml/
  def suiteName = matcher[0][1]
  def relativePath = ("${file.path}" =~ /${projectDir}\//).replaceFirst("")
    task "runTestSuite${suiteName.capitalize()}"(type: Test) {
     // need to get relative path
    useTestNG() {
       suites "${relativePath}"
    }
  }
}

This is working great. The problem is that if my test task succeeds, the task will get marked as ‘UP-TO-DATE’ on subsequent runs and skipped.

Are there suggests on how I can change this behavior such that my Test task will always run, even if a previous build succeeded and nothing changes?

Thanks.

Doug

An answer from the man himself… thank you so much. I had to modify the syntax a bit, but you set me in the right direction.

Looks like I need

task ... {
   outputs.upToDateWhen { false }
}

With that it worked.

BTW… look forward to your talk at the end of November @ Project Automation Experience in Ft. Lauderdale. Just booked last week.

Looking forward to meeting you there. Thanks for the erratum. I have fixed my initial posting.

Just what I was looking for, as I wish to force integration tests in src/intTest to run without an associated clean. Thanks.

But when I went to read about what

outputs.upToDateWhen { false }

does in the current API docs

http://gradle.org/docs/current/javadoc/index.html

I found that getOutputs() is a method on org.gradle.api.internal.AbstractTask, which is a class that has no Javadoc/Groovydoc on the API site.

Where is the documentation on Test.getOutputs() ?

Thank you.

Incidentally, I have a few subprojects that all have this type of canonical integration-test-like form:

task intTest(type: Test) {

testClassesDir = sourceSets.intTest.output.classesDir

classpath = sourceSets.intTest.runtimeClasspath }

In the parent build.gradle file where allprojects{} is implemented, is there a way I can apply

outputs.upToDateWhen { false }

to each of those intTest tasks?

Thank you.

can you search on projects that have a task called intTest?

allprojects {
    configure(tasks.matching { it.name == "intTest" }) {
    outputs.upToDateWhen { false }
  }
  }

I haven’t tested it but my understanding that it’ll go through all projects and configure tasks called inTest.

Shin

There might be one problem with the above. It assumes that the intTest tasks are already created. If you do the following, you specify a configuration rule that is either applied to the existing tasks of tasks that will be added in the future:

allprojects {
   tasks.matching { task -> task.name == "intTest" }.all {
      outputs.upToDateWhen { false }
   }
}

I made not changes to my build.gradle and only did as Hans has said on the command line. It worked a charm. I was going insane trying to get my jacoco report generated…the above forced my tests to be run, so that the .exec was generated, so that my jacocoTestReport would run.

If they should always run you can do:

task ... {
   outputs.upToDateWhen { false }
}

Do rerun them on demand you can write on the command line something like: ‘gradle cleanTest build’ or ‘gradle cleanTest test’

2 Likes