Creating a task in the project source directory

In the previous section we have defined and used our own enhanced task in the same build file. Next, we are going to extract the class definition from the build file and put it in a separate file. We are going to place the file in the buildSrc project source directory.

Let's move our InfoTask to the buildSrc directory of our project. We first create the buildSrc/src/main/groovy/sample directory. We create a file named InfoTask.groovy in this directory, with the following code:

package sample

import org.gradle.api.*
import org.gradle.api.tasks.*

class InfoTask extends DefaultTask {

    String prefix = 'Current Gradle version'

    @TaskAction
    def info() {
        println "$prefix: $project.gradle.gradleVersion"
    }
}

Notice that we must add import statements for the classes of the Gradle API. These imports are implicitly added to a build script by Gradle, but if we define the task outside the build script, we must add the import statements ourselves.

In our project build file, we only have to create a new info task of type InfoTask. Notice that we must use the package name to identify our InfoTask class or add an import sample.InfoTask statement:

task info(type: sample.InfoTask) {
    prefix = 'Running Gradle'
}

defaultTasks 'info'

If we run the build, we can see that Gradle first compiles the InfoTask.groovy source file:

$ gradle
:buildSrc:compileJava UP-TO-DATE
:buildSrc:compileGroovy
:buildSrc:processResources UP-TO-DATE
:buildSrc:classes
:buildSrc:jar
:buildSrc:assemble
:buildSrc:compileTestJava UP-TO-DATE
:buildSrc:compileTestGroovy UP-TO-DATE
:buildSrc:processTestResources UP-TO-DATE
:buildSrc:testClasses UP-TO-DATE
:buildSrc:test
:buildSrc:check
:buildSrc:build
:info
Running Gradle: 1.1

BUILD SUCCESSFUL

Total time: 4.2 secs

As a matter of fact, the build task of the buildSrc directory is executed. We can customize the build of the buildSrc directory by adding a build.gradle file. In this file, we can configure the tasks, add new tasks, and do practically anything we can in a normal project build file. The buildSrc directory can even be a multi-project build.

Let's add a new build.gradle file in the buildSrc directory. We add a simple action to the build task, which prints the value 'Done building buildSrc':

// File: buildSrc/build.gradle
build.doLast {
    println 'Done building buildSrc'
}

If we run our project build, we can see the following output:

$ gradle
:buildSrc:compileJava UP-TO-DATE
:buildSrc:compileGroovy UP-TO-DATE
:buildSrc:processResources UP-TO-DATE
:buildSrc:classes UP-TO-DATE
:buildSrc:jar UP-TO-DATE
:buildSrc:assemble UP-TO-DATE
:buildSrc:compileTestJava UP-TO-DATE
:buildSrc:compileTestGroovy UP-TO-DATE
:buildSrc:processTestResources UP-TO-DATE
:buildSrc:testClasses UP-TO-DATE
:buildSrc:test UP-TO-DATE
:buildSrc:check UP-TO-DATE
:buildSrc:build
Done building buildSrc
:info
Running Gradle: 1.1

BUILD SUCCESSFUL

Total time: 3.198 secs


Writing tests

As the buildSrc directory is similar to any other Java/Groovy project, we can also create tests for our task. We have the same directory structure as that of a Java/Groovy project, and we can also define extra dependencies in the build.gradle file.

If we want to access a Project object in our test class, we can use the org.gradle.testfixtures.ProjectBuilder class. With this class, we can configure a Project object and use it in our test case. We can optionally configure the name, parent, and project directory before using the build() method to create a new Project object. We can use the Project object, for example, to add a new task with the type of our new enhanced task and see if there are any errors. ProjectBuilder is meant for low-level testing. The actual tasks are not executed.

In the following JUnit test, we test if the property value can be set. We have a second test to check if the task of type InfoTask is added to the task container of a project:

package sample

import org.junit.*
import org.gradle.api.*
import org.gradle.testfixtures.ProjectBuilder

class InfoTaskTest {

    @Test
    void createTaskInProject() {
        final Task newTask = createInfoTask()
        assert newTask instanceof InfoTask
    }

    @Test
    void propertyValueIsSet() {
        final Task newTask = createInfoTask()
        newTask.configure {
            prefix = 'Test'
        }
        assert newTask.prefix == 'Test'
    }

    private Task createInfoTask() {
        // We cannot use new InfoTask() to create a new instance,
        // but we must use the Project.task() method.
        final Project project = ProjectBuilder.builder().build()
        project.task('info', type: InfoTask)        
    }

}

In our build.gradle file in the buildSrc directory, we must add a Maven repository and the dependency on the JUnit libraries by using the following lines of code:

repositories.mavenCentral()

dependencies {
    testCompile 'junit:junit:4.10'
}

Our test is automatically executed because the test task is part of the build process for the buildSrc directory.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.119.122.82