Test With Spring Course
Save Time by Writing Less Test Code
  • Home
  • Pre-Sales FAQ
  • Support
  • Log In

/ September 7, 2017 / petrikainulainen

Running Integration Tests With Gradle – Spock Edition

Lesson Progress:
← Back to Topic

After we have finished this lesson, we:

  • Can add custom test sets to our Gradle build.
  • Know how we can compile and run integration tests which use Spock Framework.

This lesson assumes that:

  • You are familiar with JUnit 4 categories
  • You can run unit tests which use Spock Framework with Gradle
  • You are familiar with Spock Framework
  • You can create a Gradle project that can run integration tests which use JUnit 4

Watch the Lesson

 

The text version of the lesson is given in the following:

The Requirements of Our Gradle Build

The requirements of our Gradle build are:

  • Our integration tests must have a separate source directory. The src/integration-test/groovy directory must contain the source code of our integration tests.
  • Our integration tests must have a separate resource directory. The src/integration-test/resources directory must contain the resources of our integration tests.
  • We must be able to run either unit tests, integration tests, or all tests.
  • If an integration test fails, our build must fail as well.
  • Integration and unit tests must have different HTML report directories.

Let’s start by adding a new test set to our Gradle build.

Adding Test Sets to Our Gradle Build

We can add new test sets to our Gradle build by using the Gradle TestSets plugin. We can use this plugin if we are also using the java and/or groovy plugin. We can apply the Gradle TestSets plugin by following these steps:

First, we have to declare the dependencies of our build script by following these steps:

  1. Configure Gradle to use the Bintray’s JCenter Maven repository when it resolves the dependencies of our build script.
  2. Add the Gradle TestSets plugin dependency (version 1.4.2) to the classpath configuration.

After we have configured the dependencies of our build script, our build.gradle file looks as follows:

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath(
                'org.unbroken-dome.gradle-plugins:gradle-testsets-plugin:1.4.2'
        )
    }
}

apply plugin: 'groovy'
 
repositories {
    mavenCentral()
}
 
dependencies {
    compile(
            'org.slf4j:slf4j-api:1.7.25',
            'org.slf4j:slf4j-log4j12:1.7.25',
            'log4j:log4j:1.2.17'
    )
    testCompile(
            'junit:junit:4.12',
            'org.codehaus.groovy:groovy-all:2.4.11',
            'org.spockframework:spock-core:1.1-groovy-2.4'
    )
}
 
test {
    useJUnit {
        includeCategories 'com.testwithspring.master.UnitTest'
    }
    testLogging {
        showStandardStreams = true
    }
}

Second, we have to apply the Gradle TestSets plugin. After we have done this, our build.gradle file looks as follows:

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath(
                'org.unbroken-dome.gradle-plugins:gradle-testsets-plugin:1.4.2'
        )
    }
}

apply plugin: 'groovy'
apply plugin: 'org.unbroken-dome.test-sets'
 
repositories {
    mavenCentral()
}
 
dependencies {
    compile(
            'org.slf4j:slf4j-api:1.7.25',
            'org.slf4j:slf4j-log4j12:1.7.25',
            'log4j:log4j:1.2.17'
    )
    testCompile(
            'junit:junit:4.12',
            'org.codehaus.groovy:groovy-all:2.4.11',
            'org.spockframework:spock-core:1.1-groovy-2.4'
    )
}
 
test {
    useJUnit {
        includeCategories 'com.testwithspring.master.UnitTest'
    }
    testLogging {
        showStandardStreams = true
    }
}

If we are using Gradle 2.1 or newer, we can configure the dependencies of our build script and apply the required plugins by using the plugins DSL. If we decide to do so, we have to add the following snippet to our build.gradle file:

plugins {
	id 'groovy'
    id 'org.unbroken-dome.test-sets' version '1.4.2'
}

Additional Reading:

  • Gradle User Guide: 27.5.3. Legacy Plugin Application – Applying plugins with the buildscript block
  • Gradle User Guide: 27.5.2. Applying plugins with the plugins DSL

Next, we have to configure the source and resource directories of our integration tests.

Configuring the Source and Resource Directories of Our Integration Tests

We can configure the source and resource directories of our integration tests by following these steps:

First, we have to add a new test set called integrationTest to our Gradle build. After we have done this, our build.gradle file looks as follows:

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath(
                'org.unbroken-dome.gradle-plugins:gradle-testsets-plugin:1.4.2'
        )
    }
}

apply plugin: 'groovy'
apply plugin: 'org.unbroken-dome.test-sets'


testSets {
    integrationTest
}
 
repositories {
    mavenCentral()
}
 
dependencies {
    compile(
            'org.slf4j:slf4j-api:1.7.25',
            'org.slf4j:slf4j-log4j12:1.7.25',
            'log4j:log4j:1.2.17'
    )
    testCompile(
            'junit:junit:4.12',
            'org.codehaus.groovy:groovy-all:2.4.11',
            'org.spockframework:spock-core:1.1-groovy-2.4'
    )
}
 
test {
    useJUnit {
        includeCategories 'com.testwithspring.master.UnitTest'
    }
    testLogging {
        showStandardStreams = true
    }
}

This configuration adds a source set called integrationTest to our build. This means that the src/integrationTest/groovy directory contains the source code of our our integration tests and the src/integrationTest/resources directory contains the resources of our integration tests.

Second, we have to change the name of the root directory from integrationTest to integration-test. We can do this by specifying the value of the dirName configuration option.

After we have changed the name of the root directory, our build.gradle file looks as follows:

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath(
                'org.unbroken-dome.gradle-plugins:gradle-testsets-plugin:1.4.2'
        )
    }
}

apply plugin: 'groovy'
apply plugin: 'org.unbroken-dome.test-sets'


testSets {
    integrationTest { dirName = 'integration-test' }
}
 
repositories {
    mavenCentral()
}
 
dependencies {
    compile(
            'org.slf4j:slf4j-api:1.7.25',
            'org.slf4j:slf4j-log4j12:1.7.25',
            'log4j:log4j:1.2.17'
    )
    testCompile(
            'junit:junit:4.12',
            'org.codehaus.groovy:groovy-all:2.4.11',
            'org.spockframework:spock-core:1.1-groovy-2.4'
    )
}
 
test {
    useJUnit {
        includeCategories 'com.testwithspring.master.UnitTest'
    }
    testLogging {
        showStandardStreams = true
    }
}

Let’s move on and write one integration test.

Writing a Simple Integration Test

The GetMessageSpec class contains one feature method which ensures that the getMessage() method of the MessageService class returns the correct message. Also, because we want to configure the category of this specification class, we have to annotate it with the @Category annotation.

The source code of our specification class looks as follows:

import org.junit.experimental.categories.Category
import spock.lang.Specification

@Category(IntegrationTest.class)
class GetMessageSpec extends Specification {

    def messageService = new MessageService()

    def 'Get message'() {
        expect: 'Should return the correct message'
        println 'Integration test: should return the correct message'
        messageService.getMessage() == 'Hello World!'
    }
}

By the way, we print information to System.out only because it’s the easiest way to see which feature methods are run. You shouldn’t do this in a real software project.

The IntegrationTest interface is a marker interface that identifies our integration tests. Its source code looks as follows:

interface IntegrationTest {

}

Next, we have to configure the task that runs our integration tests.

Configuring the Task That Runs Our Integration Test

When we added a test set called integrationTest to our build, the Gradle TestSets plugin created a task called integrationTest that runs our integration tests. However, because we need to fulfill the requirements of our Gradle build, we have to make some changes to its configuration. We can make these changes by following these steps:

First, we have to ensure that unit tests are run before integration tests and that integration tests are run when we invoke the build task. We can do this by following these steps:

  1. Ensure that our integration tests are run before the check task and that the check task fails the build if an integration test fails.
  2. Ensure that our unit tests are run before our integration tests. This guarantees that our unit tests are run even if our integration tests fail.

After we have made these changes, our build.gradle file looks as follows:

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath(
                'org.unbroken-dome.gradle-plugins:gradle-testsets-plugin:1.4.2'
        )
    }
}

apply plugin: 'groovy'
apply plugin: 'org.unbroken-dome.test-sets'


testSets {
    integrationTest { dirName = 'integration-test' }
}

check.dependsOn integrationTest
integrationTest.mustRunAfter test
 
repositories {
    mavenCentral()
}
 
dependencies {
    compile(
            'org.slf4j:slf4j-api:1.7.25',
            'org.slf4j:slf4j-log4j12:1.7.25',
            'log4j:log4j:1.2.17'
    )
    testCompile(
            'junit:junit:4.12',
            'org.codehaus.groovy:groovy-all:2.4.11',
            'org.spockframework:spock-core:1.1-groovy-2.4'
    )
}
 
test {
    useJUnit {
        includeCategories 'com.testwithspring.master.UnitTest'
    }
    testLogging {
        showStandardStreams = true
    }
}

Second, we have to ensure that the HTML reports of unit and integration tests are written to separate report directories. If we don’t do this, the HTML reports of our unit and integration tests are created to the same report directory. In other words, if we run both unit and integration tests, we can see only the HTML report that contains the test results of our integration tests.

We can configure the report directory of a task whose type is Test by setting the value of the reports.html.destination configuration option. Because we want to use separate report directories, we have to append the name of invoked task to the reporting base directory.

After we have done this, our build.gradle file looks as follows:

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath(
                'org.unbroken-dome.gradle-plugins:gradle-testsets-plugin:1.4.2'
        )
    }
}

apply plugin: 'groovy'
apply plugin: 'org.unbroken-dome.test-sets'


testSets {
    integrationTest { dirName = 'integration-test' }
}

check.dependsOn integrationTest
integrationTest.mustRunAfter test

tasks.withType(Test) {
    reports.html.destination = file("${reporting.baseDir}/${name}")
}
 
repositories {
    mavenCentral()
}
 
dependencies {
    compile(
            'org.slf4j:slf4j-api:1.7.25',
            'org.slf4j:slf4j-log4j12:1.7.25',
            'log4j:log4j:1.2.17'
    )
    testCompile(
            'junit:junit:4.12',
            'org.codehaus.groovy:groovy-all:2.4.11',
            'org.spockframework:spock-core:1.1-groovy-2.4'
    )
}
 
test {
    useJUnit {
        includeCategories 'com.testwithspring.master.UnitTest'
    }
    testLogging {
        showStandardStreams = true
    }
}

Third, we have to configure the integrationTest task by following these steps:

  1. Ensure that our integration tests are run by JUnit. Even though JUnit is enabled by default, we have to do this because we want to make changes to the JUnit configuration.
  2. Configure JUnit to run only integration tests that belong to the IntegrationTest category. We can do this by setting the fully qualified class name of the IntegrationTest interface as the value of the includeCategories JUnit configuration option.
  3. Ensure that Gradle prints the information that is written to System.out or System.err when our integration tests are run. By the way, we have to do this only because our feature method writes information to System.out.

After we have configured the integrationTest task, our build.gradle file looks as follows:

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath(
                'org.unbroken-dome.gradle-plugins:gradle-testsets-plugin:1.4.2'
        )
    }
}

apply plugin: 'groovy'
apply plugin: 'org.unbroken-dome.test-sets'


testSets {
    integrationTest { dirName = 'integration-test' }
}

check.dependsOn integrationTest
integrationTest.mustRunAfter test

tasks.withType(Test) {
    reports.html.destination = file("${reporting.baseDir}/${name}")
}
 
repositories {
    mavenCentral()
}
 
dependencies {
    compile(
            'org.slf4j:slf4j-api:1.7.25',
            'org.slf4j:slf4j-log4j12:1.7.25',
            'log4j:log4j:1.2.17'
    )
    testCompile(
            'junit:junit:4.12',
            'org.codehaus.groovy:groovy-all:2.4.11',
            'org.spockframework:spock-core:1.1-groovy-2.4'
    )
}
 
test {
    useJUnit {
        includeCategories 'com.testwithspring.master.UnitTest'
    }
    testLogging {
        showStandardStreams = true
    }
}

integrationTest {
    useJUnit {
        includeCategories 'com.testwithspring.master.IntegrationTest'
    }
    testLogging {
        showStandardStreams = true
    }
}

Let’s move on and find out how we can run our unit and integration tests.

Running Unit and Integration Tests

We can run our tests by using one of the following options:

First, if we want to run only unit tests, we can use one of these two options:

  • We can run unit tests by running the command: gradle clean test at command prompt.
  • If we want to run our build and exclude integration tests, we have to run the command: gradle clean build -x integrationTest at command prompt.

When we run our unit tests, we should see an output that looks as follows:

$ gradle clean test

> Task :test

com.testwithspring.master.MessageServiceSpec > Get message STANDARD_OUT
    Unit test: should return the correct message

BUILD SUCCESSFUL in 7s
7 actionable tasks: 7 executed

Second, if we want to run only integration tests, we can use one of these two options:

  • We can run integration tests by running the command: gradle clean integrationTest at command prompt.
  • We can run our build and exclude unit tests by running the command: gradle clean build -x test at command prompt.

When we run our integration tests, we should see an output that looks as follows:

$ gradle clean integrationTest

> Task :integrationTest

com.testwithspring.master.GetMessageSpec > Get message STANDARD_OUT
    Integration test: should return the correct message


BUILD SUCCESSFUL in 2s
7 actionable tasks: 7 executed

Third, if we want to run all tests, we can use one of these two options:

  • We can run unit and integration tests by running the command: gradle clean test integrationTest at command prompt.
  • We can run our build by running the command: gradle clean build at command prompt.

When we run all tests, we should see an output that looks as follows:

$ gradle clean build

> Task :test

com.testwithspring.master.MessageServiceSpec > Get message STANDARD_OUT
    Unit test: should return the correct message

> Task :integrationTest

com.testwithspring.master.GetMessageSpec > Get message STANDARD_OUT
    Integration test: should return the correct message


BUILD SUCCESSFUL in 3s
10 actionable tasks: 10 executed

Additional Reading:

  • Gradle User Guide: 4.2 Excluding tasks

Let’s summarize what we learned from this lesson.

Summary

This lesson has taught us three things:

  • We can add custom test sets to our Gradle build by using the Gradle TestSets plugin.
  • Because we use the Groovy plugin, the Gradle TestSets plugin allows us to compile and run integration tests which are written by using the Groovy programming language.
  • When we add a new test set to our Gradle build, the Gradle TestSets plugin creates a task that runs the tests which belong to our custom test set.

Get the source code from Github

← Previous Lesson

Can I help you?

This is a free sample lesson of my Test With Spring course. If this lesson helped you to solve your problem, you should find out how my testing course can help you.

Support and Privacy

  • Pre-Sales FAQ
  • Support
  • Cookie Policy
  • No Bullshit Privacy Policy
  • No Bullshit Terms and Conditions

Test With Spring Course

  • Starter Package
  • Intermediate Package
  • Master Package

Free Sample Lessons

  • Introduction to JUnit 4
  • Introduction to Unit Testing
  • Introduction to Integration Testing
  • Introduction to End-to-End Testing
  • Introduction to Spock Framework
  • Introduction to Integration Testing – Spock Edition
  • Writing End-to-End Tests With Spock Framework

Copyright Koodikupla Oy 2016 — Built on Thesis by Themedy

This website collects some information from you. The collected information is described on the privacy policy.CloseRead Privacy Policy