Writing End-to-End Tests With Spock Framework – Configuration (Spring Boot Edition)
After we have finished this lesson, we:
- Understand how we can start our Spring Boot application before our end-to-end tests are run.
- Know how we can configure our end-to-end tests by using a custom test execution listener.
- Can initialize our database into a known state before a feature method is run.
This lesson assumes that:
- You can run your end-to-end tests by using either Maven or Gradle
- You are familiar with Selenium WebDriver
- You can configure your end-to-end tests when you are using JUnit
- You are familiar with Spock Framework
Important note:
You must finish the lessons: Configuring Our End-to-End Tests - Spring Boot
and Initializing Our Database With the @Sql Annotation
before you continue this lesson. These lessons describe how you can start your Spring Boot application, create a custom TestExecutionListener that configures Selenium WebDriver, and iniatialize your database into a known state by using the @Sql annotation.
Because I don’t want to repeat myself, this lesson doesn’t provide a comprehensive description of these techniques. The goal of this lesson is to simply demonstrate how you can use these techniques when you are writing end-to-end tests with Spock framework.
Configuring Our End-to-End Tests
We can configure our end-to-end tests by following these steps:
First, we have to create a new specification class and ensure that its feature methods are run when we run our end-to-end tests. After we have created a new specification class, its source code looks as follows:
1import org.junit.experimental.categories.Category
2import spock.lang.Specification
3
4@Category(EndToEndTest.class)
5class ExampleSpec extends Specification {
6
7}
Second, we have to load the application context of our Spring Boot application. After we have done this, the source code of our specification class looks as follows:
1import org.junit.experimental.categories.Category
2import org.springframework.boot.test.context.SpringBootTest
3import spock.lang.Specification
4
5@SpringBootTest(classes = TaskTrackerApplication.class)
6@Category(EndToEndTest.class)
7class ExampleSpec extends Specification {
8
9}
Third, we have to ensure that our Spring Boot application is started when its application context is loaded. Also, we must remember to specify the port that is listened by the started Spring Boot application. Because our example uses the default port (8080), we don’t have to make any other changes to our configuration.
After we have made the required changes to our specification class, its source code looks as follows:
1import org.junit.experimental.categories.Category
2import org.springframework.boot.test.context.SpringBootTest
3import org.springframework.boot.test.context.SpringBootTest.WebEnvironment
4import spock.lang.Specification
5
6@SpringBootTest(classes = TaskTrackerApplication.class,
7 webEnvironment = WebEnvironment.DEFINED_PORT
8)
9@Category(EndToEndTest.class)
10class ExampleSpec extends Specification {
11
12}
Fourth, we have to specify the Spring profile that is used when the feature methods of our specification class are run (endToEndTest). After we have done this, the source code of our specification class looks as follows:
1import org.junit.experimental.categories.Category
2import org.springframework.boot.test.context.SpringBootTest
3import org.springframework.boot.test.context.SpringBootTest.WebEnvironment
4import org.springframework.test.context.ActiveProfiles
5import spock.lang.Specification
6
7@SpringBootTest(classes = TaskTrackerApplication.class,
8 webEnvironment = WebEnvironment.DEFINED_PORT
9)
10@ActiveProfiles(Profiles.END_TO_END_TEST)
11@Category(EndToEndTest.class)
12class ExampleSpec extends Specification {
13
14}
Fifth, we have to configure Selenium WebDriver by using the custom TestExecutionListener that we created in the lesson: Configuring Our End-to-End Tests - Spring Boot
. We can do this by following these steps:
- Annotate our specification class with the
@SeleniumTestannotation and ensure that the type of the createdWebDriverobject isChromeDriver. - Add a
WebDriverfield to our specification class and ensure that the createdWebDriverobject is injected into that field.
After we have configured Selenium WebDriver, the source code of our specification class looks as follows:
1import org.junit.experimental.categories.Category
2import org.openqa.selenium.WebDriver
3import org.openqa.selenium.chrome.ChromeDriver
4import org.springframework.beans.factory.annotation.Autowired
5import org.springframework.boot.test.context.SpringBootTest
6import org.springframework.boot.test.context.SpringBootTest.WebEnvironment
7import org.springframework.test.context.ActiveProfiles
8import spock.lang.Specification
9
10@SpringBootTest(classes = TaskTrackerApplication.class,
11 webEnvironment = WebEnvironment.DEFINED_PORT
12)
13@SeleniumTest(driver = ChromeDriver.class)
14@ActiveProfiles(Profiles.END_TO_END_TEST)
15@Category(EndToEndTest.class)
16class ExampleSpec extends Specification {
17
18 @Autowired
19 WebDriver browser
20}
Sixth, we have ensure that the existing data is deleted from the database after a feature method has been run. After we have made the required changes to our specification class, its source code looks as follows:
1import org.junit.experimental.categories.Category
2import org.openqa.selenium.WebDriver
3import org.openqa.selenium.chrome.ChromeDriver
4import org.springframework.beans.factory.annotation.Autowired
5import org.springframework.boot.test.context.SpringBootTest
6import org.springframework.boot.test.context.SpringBootTest.WebEnvironment
7import org.springframework.test.context.ActiveProfiles
8import org.springframework.test.context.jdbc.Sql
9import spock.lang.Specification
10
11import static org.springframework.test.context.jdbc.Sql.ExecutionPhase.AFTER_TEST_METHOD
12
13@SpringBootTest(classes = TaskTrackerApplication.class,
14 webEnvironment = WebEnvironment.DEFINED_PORT
15)
16@SeleniumTest(driver = ChromeDriver.class)
17@Sql(
18 value = 'classpath:/com/testwithspring/master/cleandb.sql',
19 executionPhase = AFTER_TEST_METHOD
20)
21@ActiveProfiles(Profiles.END_TO_END_TEST)
22@Category(EndToEndTest.class)
23class ExampleSpec extends Specification {
24
25 @Autowired
26 WebDriver browser
27}
Seventh, we have to initialize our database into a known state before a feature method is run. We can do this by following these steps:
- Insert the user data into our database.
- Insert the task data into our database.
After we have made the required changes to our specification class, its source code looks as follows:
1import org.junit.experimental.categories.Category
2import org.openqa.selenium.WebDriver
3import org.openqa.selenium.chrome.ChromeDriver
4import org.springframework.beans.factory.annotation.Autowired
5import org.springframework.boot.test.context.SpringBootTest
6import org.springframework.boot.test.context.SpringBootTest.WebEnvironment
7import org.springframework.test.context.ActiveProfiles
8import org.springframework.test.context.jdbc.Sql
9import spock.lang.Specification
10
11import static org.springframework.test.context.jdbc.Sql.ExecutionPhase.AFTER_TEST_METHOD
12
13@SpringBootTest(classes = TaskTrackerApplication.class,
14 webEnvironment = WebEnvironment.DEFINED_PORT
15)
16@SeleniumTest(driver = ChromeDriver.class)
17@Sql(value = [
18 'classpath:/com/testwithspring/master/users.sql',
19 'classpath:/com/testwithspring/master/tasks.sql'
20])
21@Sql(
22 value = 'classpath:/com/testwithspring/master/cleandb.sql',
23 executionPhase = AFTER_TEST_METHOD
24)
25@ActiveProfiles(Profiles.END_TO_END_TEST)
26@Category(EndToEndTest.class)
27class ExampleSpec extends Specification {
28
29 @Autowired
30 WebDriver browser
31}
We can now configure our end-to-end tests when we are using Spock Framework. Also, this configuration allows us to configure the state of the WebDriver object before a feature method is run and clear the state of the WebDriver object after a feature method has been run. For example, we can implement a setup() method that logs a user in and write a cleanup() method that logs the user out.
Let’s summarize what we learned from this lesson.
Summary
This lesson has taught us four things:
- We can start our Spring Boot application by setting the value of the
@SpringBootTestannotation’swebEnvironmentattribute toWebEnvironment.DEFINED_PORT. - Our custom
TestExecutionListenercreates a newWebDriverobject and injects the created object into a Spock specification. - We can initialize the state of the
WebDriverobject in thesetup()method and clean its state in thecleanup()method. - We can initialize our database into a known state by annotating our specification class with the required
@Sqlannotations.