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:
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:
1testSets {
2 integrationTest { dirName = 'integration-test' }
3 endToEndTest { dirName = 'end-to-end-test' }
4}
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
endToEndTestCompiledependency 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
endToEndTestRuntimedependency 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:
1dependencies {
2 endToEndTestCompile(
3 //Add dependencies that are required to compile
4 //our end-to-end tests.
5 )
6 endToEndTestRuntime(
7 //Add dependencies that are required to run
8 //our end-to-end tests.
9 )
10}
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
checktask and that thechecktask 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:
1check.dependsOn integrationTest
2check.dependsOn endToEndTest
3endToEndTest.mustRunAfter integrationTest
4integrationTest.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
EndToEndTestcategory. We can do this by setting the fully qualified class name of theEndToEndTestinterface as the value of theincludeCategoriesJUnit configuration option. - Ensure that Gradle prints the information that is written to
System.outorSystem.errwhen 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:
1endToEndTest {
2 useJUnit {
3 includeCategories 'com.testwithspring.intermediate.EndToEndTest'
4 }
5 testLogging {
6 showStandardStreams = true
7 }
8}
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
classpathconfiguration.
After we have configured the dependencies of our build script, the relevant part of our build.gradle file looks as follows:
1buildscript {
2 repositories {
3 jcenter()
4 }
5 dependencies {
6 classpath(
7 'io.spring.gradle:dependency-management-plugin:1.0.0.RELEASE',
8 'org.unbroken-dome.gradle-plugins:gradle-testsets-plugin:1.2.0',
9 'org.akhikhl.gretty:gretty:+'
10 )
11 }
12}
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:
1apply plugin: 'java'
2apply plugin: 'war'
3apply plugin: 'io.spring.dependency-management'
4apply plugin: 'org.unbroken-dome.test-sets'
5apply 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:
1gretty {
2 httpPort = 8080
3 contextPath = '/'
4 servletContainer = 'jetty9.3'
5 integrationTestTask = 'endToEndTest'
6}
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:
1gradle clean endToEndTest
When we run this command at command prompt and our web application uses Spring Framework, we should see the following output:
1:clean
2:prepareInplaceWebAppFolder
3:createInplaceWebAppFolder UP-TO-DATE
4:compileJava
5:processResources
6:classes
7:prepareInplaceWebAppClasses
8:prepareInplaceWebApp
9:compileTestJava
10:processTestResources UP-TO-DATE
11:testClasses
12:appBeforeIntegrationTest
13
1418:06:21 INFO Jetty 9.3.8.v20160314 started and listening on port 8080
1518:06:21 INFO runs at:
1618:06:21 INFO http://localhost:8080/
17:compileEndToEndTestJava
18:processEndToEndTestResources UP-TO-DATE
19:endToEndTestClasses
20:endToEndTest
21
22com.testwithspring.intermediate.message.ShowMessageText > shouldOpenFrontPage
23STANDARD_ERROR
24Starting ChromeDriver 2.27.440174 (e97a722caafc2d3a8b807ee115bfb307f7d2cfd9) on port 3918
25Only local connections are allowed.
26
27com.testwithspring.intermediate.message.ShowMessageText > shouldOpenFrontPage
28STANDARD_OUT
29
30:appAfterIntegrationTest
31
3218:06:24 INFO Destroying Spring FrameworkServlet 'dispatcher'
332017-03-05 18:06:24,238 INFO - onfigWebApplicationContext - Closing Root WebApplicationContext:
34startup date [Sun Mar 05 18:06:20 EET 2017]; root of context hierarchy
3518:06:24 INFO Closing Spring root WebApplicationContext
36Server stopped.
37
38BUILD SUCCESSFUL
39
40Total 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
endToEndTesttask. - 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:
1:clean
2:compileJava
3:processResources
4:classes
5:war
6:assemble
7:compileTestJava
8:processTestResources UP-TO-DATE
9:testClasses
10:test
11
12com.testwithspring.intermediate.message.MessageControllerTest >
13com.testwithspring.intermediate.message.MessageControllerTest$ShowMessage.shouldRenderShowMessageView STANDARD_OUT
14
15com.testwithspring.intermediate.message.MessageControllerTest >
16com.testwithspring.intermediate.message.MessageControllerTest$ShowMessage.shouldReturnHttpStatusCodeOk STANDARD_OUT
17
18:processIntegrationTestResources UP-TO-DATE
19:integrationTestClasses
20:integrationTest
21
22com.testwithspring.intermediate.message.ShowMessageTest STANDARD_OUT
23
24com.testwithspring.intermediate.message.ShowMessageTest >
25shouldRenderShowMessageView STANDARD_OUT
26
27com.testwithspring.intermediate.message.ShowMessageTest >
28shouldForwardUserToShowMessagePage STANDARD_OUT
29
30com.testwithspring.intermediate.message.ShowMessageTest >
31shouldReturnHttpStatusCodeOk STANDARD_OUT
32
33:prepareInplaceWebAppFolder
34:createInplaceWebAppFolder UP-TO-DATE
35:prepareInplaceWebAppClasses
36:prepareInplaceWebApp
37:appBeforeIntegrationTest
38
3918:16:45 INFO Jetty 9.3.8.v20160314 started and listening on port 8080
4018:16:45 INFO runs at:
4118:16:45 INFO http://localhost:8080/
42:compileEndToEndTestJava
43:processEndToEndTestResources UP-TO-DATE
44:endToEndTestClasses
45:endToEndTest
46
47com.testwithspring.intermediate.message.ShowMessageText >
48shouldOpenFrontPage STANDARD_ERROR
49
50Starting ChromeDriver 2.27.440174 (e97a722caafc2d3a8b807ee115bfb307f7d2cfd9) on port 32627
51Only local connections are allowed.
52
53com.testwithspring.intermediate.message.ShowMessageText >
54shouldOpenFrontPage STANDARD_OUT
55
5618:16:47 INFO Destroying Spring FrameworkServlet 'dispatcher'
572017-03-05 18:16:47,740 INFO - onfigWebApplicationContext - Closing Root WebApplicationContext:
58startup date [Sun Mar 05 18:16:44 EET 2017]; root of context hierarchy
5918:16:47 INFO Closing Spring root WebApplicationContext
60Server stopped.
61:check
62:build
63
64BUILD SUCCESSFUL
65
66Total 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.