Running End-to-End Tests With Gradle
After we have finished this lesson, we
- Know how we can configure the source and resource directories of our end-to-end tests.
- Understand how we can declare the dependencies of our end-to-end tests.
- Can start our web application before our end-to-end tests are run and stop it after our end-to-end tests have been run.
- Understand how we can run end-to-end tests with Gradle.
This lesson assumes that:
Watch the Lesson
The text version of this lesson is given in the following:
The Requirements of Our Gradle Build
The requirements of our Gradle build are:
- Our end-to-end tests must have a separate source directory. The src/end-to-end-test/java directory must contain the source code of our end-to-end tests.
- Our end-to-end tests must have a separate resource directory. The src/end-to-end-test/resources directory must contain the resources of our end-to-end tests.
- We must be able to run either unit tests, integration tests, end-to-end tests, or all tests.
- If an end-to-end test fails, our build must fail as well.
- Integration, unit, and end-to-end tests must have different HTML report directories.
Let’s start by configuring the source and resource directories of our end-to-end tests.
Configuring the Source and Resource Directories of Our End-to-End Tests
As we remember, we can configure the source and resource directories of our end-to-end tests by using the Gradle TestSets plugin.
Because we have already applied and configured this plugin, we can configure the source and resource directories of our end-to-end tests by adding a new test set called endToEndTest
to our Gradle build. When we add this test set to our Gradle build, we must ensure that the root directory of the created source set is: src/end-to-end-test.
After we have added a new test set to our Gradle build, the relevant part of our build.gradle file looks as follows:
testSets { integrationTest { dirName = 'integration-test' } endToEndTest { dirName = 'end-to-end-test' } }
Additional Reading:
This configuration adds a source set called: endToEndTest
to our build and configures the root directory of the source set. In other words, the src/end-to-end-test/java directory contains the source code of our our end-to-end tests and the src/end-to-end-test/resources directory contains the resources of our end-to-end tests.
Let’s move on and find out how we can declare the dependencies of our end-to-end tests.
Declaring the Dependencies of Our End-to-End Tests
When we added a new test set to our build, the Gradle TestSets plugin created two dependency configurations that are described in the following:
- The
endToEndTestCompile
dependency configuration contains the dependencies that are required to compile our end-to-end tests. It also contains all dependencies that are required to compile our unit tests. - The
endToEndTestRuntime
dependency configuration contains the dependencies that are needed when our end-to-end tests are run. It also contains all dependencies that are required to compile our end-to-end tests and to run our unit tests.
In other words, when we want to configure the dependencies of our end-to-end tests, we have to add the following snippet to our build.gradle file:
dependencies { endToEndTestCompile( //Add dependencies that are required to compile //our end-to-end tests. ) endToEndTestRuntime( //Add dependencies that are required to run //our end-to-end tests. ) }
Additional Reading:
Next, we will configure the task that runs our end-to-end tests.
Configuring the Task That Runs Our End-to-End Tests
When we added a test set called endToEndTest
to our build, the Gradle TestSets plugin created a task called endToEndTest
that runs our end-to-end 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 integration tests are run before end-to-end tests and that end-to-end tests are run when we invoke the build
task. We can do this by following these steps:
- Ensure that our end-to-end tests are run before the
check
task and that thecheck
task fails the build if an end-to-end test fails. - Ensure that our integration tests are run before our end-to-end tests. This guarantees that our integration tests are run even if our end-to-end tests fail.
After we have made these changes, the relevant part of our build.gradle file looks as follows:
check.dependsOn integrationTest check.dependsOn endToEndTest endToEndTest.mustRunAfter integrationTest integrationTest.mustRunAfter test
Additional Reading:
Second, we have to configure the endToEndTest
task by following these steps:
- Ensure that our end-to-end 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.
- Configure JUnit to run only end-to-end tests that belong to the
EndToEndTest
category. We can do this by setting the fully qualified class name of theEndToEndTest
interface as the value of theincludeCategories
JUnit configuration option. - Ensure that Gradle prints the information that is written to
System.out
orSystem.err
when our end-to-end tests are run. By the way, we have to do this only if our end-to-end tests write information toSystem.out
.
After we have configured the endToEndTest
task, the relevant part of our build.gradle file looks as follows:
endToEndTest { useJUnit { includeCategories 'com.testwithspring.intermediate.EndToEndTest' } testLogging { showStandardStreams = true } }
Let’s move on and find out how we can start and stop our web application.
Starting and Stopping Our Web Application
Before we can run our end-to-end tests, we have to start our web application before our end-to-end tests are run and stop it after our end-to-end tests have been run. If we are using Spring Framework, we can run our web application by using the Gretty Gradle plugin. We can configure this plugin by following these steps:
First, we have to declare the dependencies of our build script by following these steps:
- Configure Gradle to use the Bintray’s JCenter Maven repository when it resolves the dependencies of our build script.
- Add the Gretty Gradle plugin dependency to the
classpath
configuration.
After we have configured the dependencies of our build script, the relevant part of our build.gradle file looks as follows:
buildscript { repositories { jcenter() } dependencies { classpath( 'io.spring.gradle:dependency-management-plugin:1.0.0.RELEASE', 'org.unbroken-dome.gradle-plugins:gradle-testsets-plugin:1.2.0', 'org.akhikhl.gretty:gretty:+' ) } }
Second, we have to apply the Gretty Gradle plugin. After we have done this, the relevant part of our build.gradle
file looks as follows:
apply plugin: 'java' apply plugin: 'war' apply plugin: 'io.spring.dependency-management' apply plugin: 'org.unbroken-dome.test-sets' apply plugin: 'org.akhikhl.gretty'
Third, we have to configure the Gretty Gradle plugin by following these steps:
- Ensure that used servlet container listens to the port 8080.
- Configure the context path of our application.
- Ensure that our application is run by using Jetty 9.3.
- Ensure that Gretty starts our web application before our end-to-end tests are run and stops it after our end-to-end tests have been run.
After we have configured the Gretty Gradle plugin, the relevant part of our build.gradle file looks as follows:
gretty { httpPort = 8080 contextPath = '/' servletContainer = 'jetty9.3' integrationTestTask = 'endToEndTest' }
If we are using Spring Boot, we can start and stop our application by leveraging its testing support. We will talk more about this when we learn to configure our end-to-end tests.
Additional Reading:
We are now ready to run our end-to-end tests. Let’s find out how we can do it.
Running End-to-End Tests
We can run our end-to-end tests by using one of the following options:
First, we can run our end-to-end tests by using the command:
gradle clean endToEndTest
When we run this command at command prompt and our web application uses Spring Framework, we should see the following output:
:clean :prepareInplaceWebAppFolder :createInplaceWebAppFolder UP-TO-DATE :compileJava :processResources :classes :prepareInplaceWebAppClasses :prepareInplaceWebApp :compileTestJava :processTestResources UP-TO-DATE :testClasses :appBeforeIntegrationTest 18:06:21 INFO Jetty 9.3.8.v20160314 started and listening on port 8080 18:06:21 INFO runs at: 18:06:21 INFO http://localhost:8080/ :compileEndToEndTestJava :processEndToEndTestResources UP-TO-DATE :endToEndTestClasses :endToEndTest com.testwithspring.intermediate.message.ShowMessageText > shouldOpenFrontPage STANDARD_ERROR Starting ChromeDriver 2.27.440174 (e97a722caafc2d3a8b807ee115bfb307f7d2cfd9) on port 3918 Only local connections are allowed. com.testwithspring.intermediate.message.ShowMessageText > shouldOpenFrontPage STANDARD_OUT :appAfterIntegrationTest 18:06:24 INFO Destroying Spring FrameworkServlet 'dispatcher' 2017-03-05 18:06:24,238 INFO - onfigWebApplicationContext - Closing Root WebApplicationContext: startup date [Sun Mar 05 18:06:20 EET 2017]; root of context hierarchy 18:06:24 INFO Closing Spring root WebApplicationContext Server stopped. BUILD SUCCESSFUL Total time: 11.888 secs
This output reveals us three things:
- The Gretty Gradle plugin starts our web application before our end-to-end tests are run.
- Gradle runs our end-to-end tests when we run the
endToEndTest
task. - The Gretty Gradle plugin stops our web application after our end-to-end tests have been run.
Second, if we want to run all tests, we can use one of these two options:
- We can run unit, integration, and end-to-end tests by running the command: gradle clean test integrationTest endToEndTest at command prompt.
- We can run our build by running the command: gradle clean build at command prompt.
When we run all tests and our web application uses Spring Framework, we should see an output that looks as follows:
:clean :compileJava :processResources :classes :war :assemble :compileTestJava :processTestResources UP-TO-DATE :testClasses :test com.testwithspring.intermediate.message.MessageControllerTest > com.testwithspring.intermediate.message.MessageControllerTest$ShowMessage.shouldRenderShowMessageView STANDARD_OUT com.testwithspring.intermediate.message.MessageControllerTest > com.testwithspring.intermediate.message.MessageControllerTest$ShowMessage.shouldReturnHttpStatusCodeOk STANDARD_OUT :processIntegrationTestResources UP-TO-DATE :integrationTestClasses :integrationTest com.testwithspring.intermediate.message.ShowMessageTest STANDARD_OUT com.testwithspring.intermediate.message.ShowMessageTest > shouldRenderShowMessageView STANDARD_OUT com.testwithspring.intermediate.message.ShowMessageTest > shouldForwardUserToShowMessagePage STANDARD_OUT com.testwithspring.intermediate.message.ShowMessageTest > shouldReturnHttpStatusCodeOk STANDARD_OUT :prepareInplaceWebAppFolder :createInplaceWebAppFolder UP-TO-DATE :prepareInplaceWebAppClasses :prepareInplaceWebApp :appBeforeIntegrationTest 18:16:45 INFO Jetty 9.3.8.v20160314 started and listening on port 8080 18:16:45 INFO runs at: 18:16:45 INFO http://localhost:8080/ :compileEndToEndTestJava :processEndToEndTestResources UP-TO-DATE :endToEndTestClasses :endToEndTest com.testwithspring.intermediate.message.ShowMessageText > shouldOpenFrontPage STANDARD_ERROR Starting ChromeDriver 2.27.440174 (e97a722caafc2d3a8b807ee115bfb307f7d2cfd9) on port 32627 Only local connections are allowed. com.testwithspring.intermediate.message.ShowMessageText > shouldOpenFrontPage STANDARD_OUT 18:16:47 INFO Destroying Spring FrameworkServlet 'dispatcher' 2017-03-05 18:16:47,740 INFO - onfigWebApplicationContext - Closing Root WebApplicationContext: startup date [Sun Mar 05 18:16:44 EET 2017]; root of context hierarchy 18:16:47 INFO Closing Spring root WebApplicationContext Server stopped. :check :build BUILD SUCCESSFUL Total time: 14.357 secs
Let’s summarize what we learned from this lesson.
Summary
This lesson has taught us four things:
- We can add custom test sets to our Gradle build by using the Gradle TestSets plugin.
- The Gradle TestSets plugin creates dependency configurations that we can use when we declare the dependencies of our end-to-end tests.
- If our web application uses Spring Framework, we can start and stop it by using the Gretty Gradle plugin.
- 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.
Previous LessonNext Lesson