3

Let's say that I have created separate tasks for running integration and acceptance tests in my gradle build script. When I run the build task I want to run testing tasks before in this order: unit tests(test task), integration tests (intergationTest task) and acceptance tests (acceptanceTest task). Is this possible and how?

Rade Milovic
  • 965
  • 4
  • 13
  • 29

6 Answers6

3

You are looking for "should run after" described in Gradle documentation - http://www.gradle.org/docs/current/userguide/more_about_tasks.html

Radim
  • 4,721
  • 1
  • 22
  • 25
  • As I can see it only specifies one task been run after the another. I want to run three tasks before build task. I can surely do that by this command but that would mean that if I run test task only two more would be run and I don't want that. – Rade Milovic Oct 18 '14 at 15:32
  • Have you tried it? `taskY.shouldRunAfter taskX1, taskX2` works. http://www.gradle.org/docs/current/javadoc/org/gradle/api/Task.html#shouldRunAfter(java.lang.Object...) – Radim Oct 18 '14 at 18:03
  • I know that this is possible, but I want this to happed only when build is called. – Rade Milovic Oct 18 '14 at 18:35
  • I've asked the same question on official Gradle forum and got the answer. You can see it here: http://forums.gradle.org/gradle/topics/how-to-inject-tasks-between-test-and-build-task?rfm=1 Your answer was pretty close so I will mark it as usefull. – Rade Milovic Oct 18 '14 at 18:43
  • Updated link to gradle forum discussion: https://discuss.gradle.org/t/how-to-inject-tasks-between-test-and-build-task/5165 – ksceriath Nov 30 '20 at 04:32
2

Here's how you can do it without creating artificial dependencies:

https://caffeineinduced.wordpress.com/2015/01/25/run-a-list-of-gradle-tasks-in-specific-order/

TLDR; version:

//--- build aliases : define a synonym here if you want a shortcut to run multiple targets

def buildAliases = [
   'all' : ['clean', 'assemble', 'runProvisioner', 'stopTomcat', 'installTomcat', 'deployToTomcat', 'startTomcat'],
   'rebuild' : ['clean', 'assemble']
]
def expandedTaskList = []

gradle.startParameter.taskNames.each {
    expandedTaskList << (buildAliases[it] ? buildAliases[it] : it)
}

gradle.startParameter.taskNames = expandedTaskList.flatten()

println "\n\n\texpanded task list: ${gradle.startParameter.taskNames }\n\n"
Lance
  • 682
  • 6
  • 12
1

This is what I did on my projects.

check.dependsOn integTest
integTest.mustRunAfter test
tasks.withType(Pmd) {
  mustRunAfter integTest // Pointing to a task
}
tasks.withType(FindBugs) {
  mustRunAfter tasks.withType(Pmd) // Pointing to a group of tasks under Pmd
}
tasks.withType(Checkstyle) {
  mustRunAfter tasks.withType(FindBugs)
}

It helped me to order tasks by group.

sancho21
  • 3,511
  • 1
  • 39
  • 45
1

I created this helper method based on a solution that I found on Gradle forum.

Task.metaClass.runFirst = { Task... others ->
    delegate.dependsOn(others)
    delegate.mustRunAfter(others[0])
    for (def i=0; i < others.size() - 1; i++) {
        def before = others[i]
        def after = others[i+1]
        after.mustRunAfter(before)
    }
}

Then you can create tasks X, A, B and C and use like this:

X.runFirst A, B, C
Topera
  • 12,223
  • 15
  • 67
  • 104
0

The first answer in the list turned out to be great for me. I used

X.shouldRunAfter Y

  • Hello! Welcome to the Stackoverflow community. Just advice: In case you want to admit that [Radim's answer](https://stackoverflow.com/a/26441372/7597651) is worked for you - it's better to upvote his answer or leave a comment in his answer. It will bring attention to the answer your consider the correct one. No need to submit a separate answer for such purpose. – mykhailo.romaniuk Feb 19 '20 at 12:23
0

UPDATE: While using this "solution" for a short while i found out, that it does not work 100% as intended. I don't know why though. Any help to make it work would be appreciated. Maybe it does not work properly when there is more than one task in the Set?! While testing i did add some dummy-Tasks which only printed a text inbetween each of the other tasks and all seemed to be ok.


After some attempts with other solutions i came up with this solution:
It uses the mustRunAfter command to chain Sets of Tasks into the required order.

I'm working with Sets instead of individual Tasks, because i got circular dependency issues otherwise, since some tasks already depended on each other.

Also important to note: the isNotEmpty() check was essential, as it would otherwise break the enforced ordering if an ampty set was passed to the method.

tasks.register("cleanAndGenerate") {
    var lastTasks: Set<Task> = setOf()

    fun findTasks(taskName: String): Set<Task> {
        return if (taskName.startsWith(":")) { // task in specific sub-project
            setOf(tasks.findByPath(taskName)!!)
        } else { // tasks in all (sub-)projects
            getTasksByName(taskName, true)
        }
    }

    fun dependsOnSequential(taskName: String) {
        val tasks = findTasks(taskName)
        tasks.forEach { task -> task.mustRunAfter(lastTasks) }
        dependsOn(tasks)
        if (tasks.isNotEmpty()) {
            lastTasks = tasks
        }
    }

    dependsOnSequential(":project1:clean") // task in specific sub-project
    dependsOnSequential(":project2:clean")
    dependsOnSequential("task1") // tasks in all (sub-)projects
    dependsOnSequential("task2")
    // add more as needed
}
Frederic Leitenberger
  • 1,949
  • 24
  • 32