How can I start a server conditionally before a functionalTestRun?

I’ve been trying to avoid starting a server when there are no tests to run (because they are up-to-date).

:serverRun
  :funcTestTask
  :serverStop

a subsequent run looks like

:serverRun
   :funcTestTask UP-TO-DATE
  :serverStop

but what I really want is for it look like this

:serverRun UP-TO-DATE
  :funcTestTask UP-TO-DATE

I’ve tried setting the inputs and outputs of the two tasks the same

serverRun.inputs.files(funcTest.inputs)
serverRun.outputs.files(funcTest.ouputs)

and this works fine in most cases EXCEPT when the funcTestTask needs to run again due to test failure, what happens is

:serverRun
  :funcTestTask FAILED
  :serverStop (because of finalized)

and a subsequent run looks like

:serverRun UP-TO-DATE
  :funcTestTask FAILED
  :serverStop

Is there something about the evaluation of the output for UP-TO-DATEness that I’m simply not understanding? Presumably there is something about the output of the funcTestTask that triggers a rerun, but even with the same output files the server doesn’t run again.

What you have to understand is that during the first run, when the tasks failed, the funcTestTask didn’t complete, so it didn’t snapshot the outputs. ServerRun DID complete, so it did snapshot its outputs. So on the second run, the inputs/outputs for serverRun haven’t changed, so it happily skips it while the outputs aren’t cached for funcTestTask and so it must re-run it.

You might be able to do something clever with a task listener and a trigger file. So, serverRun has the trigger file as an input and you only change it if the test task fails:

serverRun {
  ext.trigger = file("${buildDir}/trigger")
  inputs.files trigger
}
  gradle.taskGraph.afterTask { Task task, TaskState state ->
    if (task.name == "funcTestTask" && state.failure) {
        serverRun.trigger << new Date()
    }
}

I haven’t really thought this through, and there might be some pathological cases here (i.e. use at your own risk), but that might give you something to work with.

Thanks, this actually works pretty well.

Is there a difference between using

serverRun.inputs.files trigger

vs

serverRun.outputs.files trigger

Also has a followup, is there any way to know if the user explicity added the serverRun task to the command line. Can I differentiate between

gradle serverRun funcTest

and

gradle funcTest

mainly to explicitly run the server even if the functional test is UP-TO-DATE

For what you are doing, there’s probably not a difference, but an input seems more conceptually correct to me.

You would have to query the start parameters to find out:

if ("serverRun" in gradle.startParameter.taskNames) {
  }

Thanks. I think I got this working.