Run gradle task multiple times

2019-07-10 14:53发布

问题:

I have a gradle project containing two modules in subdirectories. The directory structure is as below.

root
    module1
        build.gradle
    module2
        build.gradle
    build.gradle
    settings.gradle

The top level settings.gradle includes the two modules. The top level build.gradle contains the following.

task runScript(type: Exec) {
    workingDir 'scripts'
    commandLine 'python3', 'myscript.py'
}

project(':module1') {
    evaluationDependsOn(':module1')

    final test = tasks.findByName('test')
    test.dependsOn(runScript)
}

project(':module2') {
    evaluationDependsOn(':module2')

    final test = tasks.findByName('test')
    test.dependsOn(runScript)
}

Task runScript sets the database to a known state and must be run before each module test task.

When I run the test task my script only executes once. How can I ensure it executes multiple times?

$ ./gradlew test 
... some output

:runScript
RUNNING MY SCRIPT

:module1:test
RUNNING MODULE1 TESTS

... some output

:module2:test
RUNNING MODULE2 TESTS

Things I Tried

I tried adding outputs.upToDateWhen {false} to the task runScript so Gradle never thinks it is up to date. This didn't make any difference; I assume because the task still only occurs once in the task graph?

I tried replacing the lines containing dependsOn for each module with test.doFirst {runScript.execute()}. This changes when the task gets executed but does not result in multiple executions.

$ ./gradlew test 
... some output

:module1:test
RUNNING MY SCRIPT
RUNNING MODULE1 TESTS

... some output

:module2:test
RUNNING MODULE2 TESTS

I tried creating a new task for each module. This works but it's duplicating code.

project(':module1') {
    evaluationDependsOn(':module1')

    final test = tasks.findByName('test')

    task runScript(type: Exec) {
        workingDir '../scripts'
        commandLine 'python3', 'myscript.py'
    }

    test.dependsOn(runScript)
}

project(':module2') {
    evaluationDependsOn(':module2')

    final test = tasks.findByName('test')

    task runScript(type: Exec) {
        workingDir '../scripts'
        commandLine 'python3', 'myscript.py'
    }

    test.dependsOn(runScript)
}

回答1:

If your script is necessary for each run of each Test task, simply assure its execution before each Test task. Why even use a task then?

subprojects {
    tasks.withType(Test) {
        doFirst {
            exec {
                workingDir 'scripts'
                commandLine 'python3', 'myscript.py'
            }
        }
    }
}