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
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.
18.119.122.82