Integration and functional testing with Spock - USING SPOCK FOR ALL KINDS OF TESTING NEEDED IN A BIG APPLICATION - Java Testing with Spock, Version 6 (2015)

Java Testing with Spock, Version 6 (2015)

PART 3: USING SPOCK FOR ALL KINDS OF TESTING NEEDED IN A BIG APPLICATION

Chapter 7. Integration and functional testing with Spock

In this chapter

· Categories of unit tests in an enterprise application

· Writing integration tests for the Spring framework

· Testing REST endpoints with Spock

· Web based tests with Spock and Geb

Using Spock as part of the build process.

At this point in the book you probably just want to get started writing Spock tests for your own application. If you are a single developer, or your application is fairly small and self-contained (e.g. a standalone utility) then the previous chapters have covered the most important Spock features you will need.

If on the other hand you are part of a bigger team that works in large enterprise applications with an existing build infrastructure (automatic builds, test environments, code quality etc.) you might be wondering how Spock will fit the existing paradigm and practices already used in your organization.

In this chapter we will see how Spock can be used for the full testing lifecycle of an enterprise application that includes multiple layers of testing procedures that run either automatically (i.e. after each code change) or on demand as part of a release. Spock is suitable for both integration tests (tests that cover multiple classes/modules and don't focus on a single class) and functional tests (i.e. tests that cover end-to-end functionality and view the whole system as a single entity instead of individual classes). As with the previous chapter, I will briefly cover the theory between these different types of tests.

Last but not least, a very popular requirement for Enterprise testing is examining web applications. We’ll see how Spock can be used in conjunction with Geb[65], another Groovy library that makes web testing very easy.

7.1 Unit tests versus integration tests versus functional tests

I will start this chapter with a brief reminder on the different types of tests useful to an Enterprise application. This knowledge is not specific to Spock, so if you already know the theory[66] feel free to skip ahead on the Spock implementation.

Each time you want to create a new unit test, you have to decide on the scope it will cover. A unit test may focus on a single class, multiple classes, a single module or even the whole system. The breadth of the tested area will affect several factors of your unit test, from the time it takes to complete (obviously the more you are trying to test the bigger the unit test execution) to the readability and effort it takes to write it (a unit test that needs to setup several modules needs more preparation).

At one end of the spectrum we have "pure" unit tests that focus on a single class. These are easy to write, run fast and only depend on the production code. At the opposite end we have functional tests (also called acceptance tests) that examine the system as a whole, emulating user behavior and even interacting with the GUI (graphical user interface). A functional test sends a request to the system and expects a response without any other knowledge for the inner workings of the system.

In the middle of the extremes, tests can either examine a code module, or a code service. These are the integration tests (because they examine how individually tested classes integrate into modules). Picture 7.1 shows the scope examined by these categories of tests.

Figure 7.1 - Unit tests focus on a single class, integration tests cover multiple modules and functional tests cover end-to-end testing from the web interface to the database.

The example used in the figure above is the eShop application already mentioned multiple times in the previous chapters.

1. Unit tests always examine a single class. All other classes are mocked/stubbed so that they do not interfere with the result of the test. An example of unit test would be to verify that the basket class correctly calculates the weight of products it contains.

2. Integration tests focus on multiple classes. Mocks/Stubs are rarely used as we are interested in both the code and the way communication happens between modules. An example of an integration test, would be to verify the communication between the warehouse inventory (that is backed by a Database) and the products contained in the basket. When the customer attempts to check-out the basket should show which products are in stock and which are not (after querying the inventory which itself queries the database).

3. Functional tests assume that the whole system is a black box. They test end-to-end interactions starting from the user interface (or the network API), and pass through the whole system. Functional testing usually requires a clone or duplicate of the real system. An example of a functional test would be an automated test that opens a browser on its own, selects some products by emulating the clicking of buttons on the web pages, checks out, enters a credit card and expects to "see" on the screen a tracking number of the order shipped.

The distinction between these three categories is not always clear. After all, concepts such as "module" may mean different things to different people. Do not get consumed by terminology.

7.1.1 Characteristics for the different test categories

A well tested application needs tests from all three categories. I sometimes imagine that a well designed software product is like a well designed car. If you are a car manufacturer you would need to test the individual screws, bolts and frames of a car (unit tests), how these are assembled together (integration tests), and in the end perform tests on the final product by driving it in a controlled environment[67] (functional tests).

It would be unrealistic to release a car without making sure that all screws are correctly assembled and it would also be foolish to release a car without actually testing it as a whole on the road. I am still puzzled when I see software organizations that either have only functional tests or only integration tests and at the same time don't understand why the bugs found on production are over expectations.

The challenge with these three categories of tests is that they have different requirements and need different accommodations in the software lifecycle of project. The following table briefly outlines the differences among them:

Table 7.1 Test categories in an enterprise application must be handled differently

Unit test

Integration

Functional Test

Scope of test

A single Java class

A single module or multiple classes

The whole system.

Focus of test

Correctness of Java class

Class communication, transactions, logging security etc.

End to End user experience

Result depends on

Java code

Java code, file system, network, DB, other systems,

Java code, file system, network, DB, other systems, GUI, API endpoints

Stability

Very stable

May break from environment changes

Very brittle (a trivial GUI change may break it)

Failed test means

A regression.

Either a regression or an environment change

A regression, an environment change, a GUI change

Effort required to write

Minimal

Medium (may need external systems)

High (needs a running replica system)

Effort required to fix

Minimal

Medium (multiple classes may have bugs)

Medium/High (Bug can be in any layer of the application)

Tools required

A test framework

Test framework, a container, a db and external services.

Specialized and sometimes proprietary external tools. A staging system.

Mocking/Stubbing

Used when needed

Rarely used if ever.

Never used

Time to run a single test

Some milliseconds

Seconds

Seconds or minutes

Time to run all tests of that type

5 minutes max

Can be hours

Can be hours

Tests are run

After every commit automatically

Automatically at various scheduled intervals

Automatically/Manually before a release

People involved

Developers

Developers, Architects

Developers, Architects, Testers, Analysts, Customer

The table above is only intended as a rough guide and it is geared towards large enterprise projects[68]. Your project might be different but the general principles still apply. You can write pure unit tests with Spock with no additional external library. But if you need to write a test that launches a web browser and starts pressing buttons in an automated manner, Spock is not enough on its own.

7.1.2 The testing pyramid

So far, all tests you have seen in the previous chapters are mainly unit tests (i.e. pure tests). You might be wondering why I devoted three whole chapters (4-5-6) for basic unit tests and only left a single chapter for both integration and functional tests.

The reason for this decision is that although all three categories of tests are essential, pure unit tests have a larger weight. This is best illustrated by the testing pyramid[69] that shows what percentage of tests from each category comprise your whole testing suite:

Figure 7.2 Break-down of total test count for each test category in a large enterprise application – the “testing pyramid”.

Pure unit tests are your first line of defense. They are the foundation where other tests build upon. It makes no sense to start creating complex integration tests, if you are not sure about the quality of the individual Java classes that comprise them.

Only after you have enough unit tests, you can start writing integration tests. Integration tests should be focused on testing things that pure unit tests cannot detect. Typical examples are transactions, security and other cross-cutting concerns in your application. Integration tests are often used to ensure correct functionality between the prior code base and new modules added to a project.

Finally, when you are happy with the amount of integration tests, it is time to create functional tests. These view the whole system as a black box[70] and should be used as a way to catch serious runtime or graphical errors that slip through the rest of the tests.

Common pitfalls with the pyramid of unit tests

If you look back at the pyramid, you can imagine that any other shape is an anti-pattern. A project that has no unit tests is clearly missing the foundations of the pyramid. A project that has too many functional tests is also problematic (the pyramid will fall under its own weight).

7.1.3 Spock support for integration and functional testing

Unfortunately, unlike pure unit tests (which can be covered using just Spock), integration tests require a different infrastructure depending of the Java framework you use. Given the amount of Java frameworks present it would be very hard to cover all possible cases.

I have chosen to cover integration testing with Spock and Spring[71] and I will also you give you pointers for JavaEE[72] and Guice[73]. Spring was chosen because of its popularity at the time of writing. I will then show you how you can test backend applications that use REST services (i.e. powered by HTTP/JSON).

I will also assume that your application has a Web interface and explain that you can use Spock and Geb together to automate the web browser for effective functional tests.Finally I will complete the puzzle by covering Maven configuration and some advice on the build server setup.

If you are writing an exotic Java application that does not match this profile, I apologize in advance. You need to do some research on your own. Either there is already a Spock extension for what you need or you can use the fact that Spock is compatible with JUnit and attempt to use a tool from the JUnit world.

7.1.4 Source code organization of the examples

Unlike other chapters, the source code for this chapter is actually three distinct projects:

Figure 7.3 - Source code contains three projects

Each project is a mini application on its own. Showing all source files in the book as code listings would be unmanageable. Instead, I will focus only on important classes so feel free to consult the Github[74] code while reading the book. The projects themselves were strictly created for illustration purposes, so take notice on the Spock tests instead of the "production" code.

7.2 Integration testing with Spock

In chapter 6 you saw various techniques to mock collaborator classes so that only the class under test affected the outcome of the tests. There are cases however where we do not want to mock collaborators but we actually want to test multiple real classes together.

An integration test, is a test that spans multiple Java class (instead of just one) and examines the communication among them. Common scenarios that need integration tests are database mappings, security constraints, communication with external systems and any other cases where testing is focused on a module rather than a single class.

7.2.1 Testing a Spring Application

As a starting example we will look at a standalone application powered by a Swing User interface that manages the warehouse inventory of an eShop.

Figure 7.4 - A simple database application with a Swing User interface

The application is based on the Spring framework and saves all its data in a JPA/Hibernate database, which in our case is an HSQLdb[75] file. The design of the application is very straightforward. In the middle we have the Spring dependency injection container and all other classes revolve around it:

Figure 7.5 - The Spring context initializes all Java classes

The Spring context that binds all other classes is an XML file defined in src/main/resources/spring-context.xml. We want to write a Spock test that examines the Hibernate mappings for the Product class. In order to achieve that we need to test the whole chain of database loading and saving. This means that the following classes should be tested:

1. The ProductLoader class which is the DAO

2. The JPA entity Manager that manages database mappings

3. The Datasource that provides access to the real Database.

The good news here is that Spock already contains a Spring extension that instantly recognizes the ContextConfiguration[76] annotation provided by the Spring test facilities as shown below:

Listing 7.1 Access Spring context from a Spock test

@ContextConfiguration(locations = "classpath:spring-context.xml") #Aclass RealDatabaseSpec extends spock.lang.Specification{ @Autowired #B ProductLoader productLoader @Sql("clear-db.sql") #C def "Testing hibernate mapping of product class"() { given: "the creation of a new product" productLoader.createDefaultProduct() #D when: "we read back that product" List<Product> allProducts = productLoader.getAllProducts(); #E then: "it should be present in the db" allProducts.size() == 1 #F and: "it should start with zero quantity" allProducts[0].getStock() ==0 #F }}

#A Marking the test with the Spring ContextConfiguration annotation

#B Wiring a Spring bean as in normal production code

#C Spring facility to initialize a database

#D Saves something to the database

#E Reads back again from the database

#F Verifies database read

If you look at listing 7.1 you will see that all testing facilities and annotations are already offered by Spring. Spock automatically understands that this file is using a Spring context and allows you to obtain and use Spring beans (in our case the ProductLoader) as in normal Java code.

The important line here is the ContextConfiguration annotation, because it is used by Spock to understand that this is a Spring based integration test. Notice also that I use the Spring Sql annotation that allows me to run an SQL file before the test runs. This is already offered by Spring and works as expected in the Spock test.

The result test is an integration test because the real database is initialized, a product is saved on it and then read back. Nothing is mocked here, so if your database is slow then this test will also run slowly.

Options for Spring Testing

The Spring framework contains a gazillion options when it comes to testing. Explaining them all is outside the scope of this book. You should consult the official Spring documentation[77]. In this chapter I am just showing some techniques that prove that Spock and Spring play very well together.

A nice facility offered by Spring, is the automatic rollback of database changes during a unit test. This is a very effective to keep your unit tests completely independent from one-another. Activating this behavior is unsurprisingly done using standard Spring facilities that apply automatically even in the case of a Spock test.

Listing 7.2 Rolling back database changes automatically

@ContextConfiguration(locations = "classpath:spring-context.xml")@Transactional #Aclass RealDatabaseSpec extends spock.lang.Specification{ @Autowired ProductLoader productLoader @Rollback #B @Sql("clear-db.sql") def "Testing hibernate mapping of product class"() { [...code redacted for brevity...] }}

#A Making this test honor transactions

#B Database changes will be reverted once the test finishes

The test code of listing 7.2 is exactly the same as 7.1. I have only added two extra Spring annotations. The Transactional annotation notifies Spring that this test will use database transactions. The Rollback annotation instructs Spring to revert back[78] all database changes performed inside the Spock feature method, once the test finishes.

This means that even if your Spock test deletes or changes data in the database, these changes will not be persisted in the end of the test suite. Again this capability is offered by Spring and Spock is completely oblivious to it.

In summary, Spock support for Spring tests is as easy as marking a test with the Spring test annotations. If you have written JUnit tests using the SpringJUnit4ClassRunner you will feel right at home.

7.2.2 Narrowing down the Spring context inside Spock tests

If you have written already Spring integration tests before, you should have noticed two serious flaws of the Spock tests shown in listings 7.1 and 7.2. Both of these tests, use the same Spring context as the production code. This means that

1. Tests use the same database as production code. This is not desirable in general and sometimes not even possible because of security constraints.

2. The Spring context initializes all Java classes even though not all of them are used in the Spock test.

For example, in the Swing application the Spock test also creates the Swing class for the GUI even though we never test the GUI. This means that the Spock tests shown in listings 7.1 and 7.2 might not run easily in a headless machine (and build servers are typically headless machines).

The recommended way to solve these issues is to use a different Spring context for the tests. The production context contains all classes of the application and the test context contains a reduced set of the classes actually tested. Thus a second XML file is created as shown below:

Figure 7.6 Creating a second Spring context just for tests.

With the reduced context you are free to redefine the beans that are active during the Spock test. Two very common techniques are replacing the real database with a memory based one and also removing beans that are not needed for the test. If you look at the contents of the reduced-text-context-file you will see that I have removed the GUI class and also replaced the file based datasource with a memory H2 DB[79] with the following line:

<jdbc:embedded-database id="dataSource" type="H2"/>

The in-memory database is much faster than a real database, but it only works for small datasets (i.e. you cannot easily use it as a clone of a real database). Since unit tests use very specific datasets (small in size) and also need to run fast, an in-memory database is a good candidate for DB testing.

This means that the context for the Spock test is now more simplified as shown below:

Figure 7.7 - Spring context just for tests uses an in-memory database and no GUI classes

To run the test, we simply inform Spring on the alternative context file. Spock automatically picks up the change:

Listing 7.3 Using a reduced Spring context for unit testing

@ContextConfiguration(locations = "classpath:reduced-test-context.xml") #A@Transactionalclass DummyDatabaseSpec extends spock.lang.Specification{ @Autowired ProductLoader productLoader def "Testing hibernate mapping of product class - mem db"() { given: "the creation of a new product" productLoader.createDefaultProduct() #B when: "we read back that product" List<Product> allProducts = productLoader.getAllProducts(); #C then: "it should be present in the db" allProducts.size() == 1 and: "it should start with zero quantity" allProducts[0].stock ==0 }}

#A Defining an alternative Spring context

#B Data is written to an in-memory database

#C Data is fetched from an in-memory database

You can find the reduced Spring context in GitHub[80]. Because this test runs with an in-memory database, it is much faster than our original test shown in listing 7.2. Also we removed the GUI class from the context so this unit test can run in any Unix/Linux system in a shell environment (the typical case for build servers)

You need to examine your own application and decide what you will discard/replace in the test context. A good starting point is by removing all beans that are not actually used in your tests.

7.2.3 Direct access to the database with Groovy SQL

At this point you have seen that a Spock test has access to Spring beans without[81] any special configuration, and that you can use common Spring features as testing aids.

The additional advantage of Spock tests is the fact that you have all Groovy tools and libraries at your disposal as well. I have tried to introduce you to some essential Groovy facilities back in chapter 2, but you should spend some extra time to explore the full Groovy documentation to see what is available that might help you while writing Spock tests for your application needs.

A handy Groovy feature not mentioned in chapter 2 (because it is mainly a nice-to-have feature) is the Groovy SQL[82] interface. The Groovy SQL class is a thin abstraction over JDBC that allows you to access a database in a very convenient way. You can think of it as a Spring JDBC template on steroids.

Let's assume that I want to verify that the DAO of the eshop brings back all products in alphabetical order. I can initialize my database using Groovy SQL:

Listing 7.4 Using Groovy SQL to prepare the DB in a Spock test

@ContextConfiguration(locations = "classpath:reduced-test-context.xml")class DummyDatabaseGroovySqlWriteSpec extends spock.lang.Specification{ @Autowired DataSource dataSource #A @Autowired ProductLoader productLoader def "Testing ordering of products"() { given: "the creation of 3 new products" Sql sql = new Sql(dataSource) #B sql.execute("DELETE FROM PRODUCT") #C sql.execute("INSERT INTO PRODUCT (id,name,price, weight,stock) VALUES (1, 'samsung',400,1,45);") #D sql.execute("INSERT INTO PRODUCT (id,name,price, weight,stock) VALUES (2, 'bravia',1200,3,2);") #D sql.execute("INSERT INTO PRODUCT (id,name,price, weight,stock) VALUES (3, 'canon',500,5,23);") #D when: "we read back the products" List<Product> allProducts = productLoader.getAllProducts(); then: "they should be ordered by name" allProducts.size() == 3 allProducts[0].name =="bravia" allProducts[1].name =="canon" allProducts[2].name =="samsung" cleanup: "remove inserted data" sql.execute("DELETE FROM PRODUCT") #E sql.close() #F } }

#A Getting the underlying datasource from Spring

#B Groovy SQL creation over an existing datasource

#C Clears the db

#D Inserts data directly on the database

#E Clean up so that other tests are unaffected

#F Always a good practice

The Groovy SQL interface is a very powerful feature. It supports all SQL statements you would expect (schema creations/data writing/data querying) and explaining all its capabilities is outside the scope of its book. It can be used both in production code and in Spock tests.

I tend to use it when I want to do something strange on the db (perhaps recreate an error condition) that is normally not possible via the DAOs of the application itself. Be careful when using it in your Spock tests because as you have seen in listing 7.4 it gets direct access to the database so it acts outside the caches of JPA/Hibernate.

Despite these shortcomings, it is a very natural Groovy way to access the DB and you will find its code very compact and comfortable. The last example can be further improved by extracting the common SQL statement in its own String.

Listing 7.5 Using Groovy SQL to prepare the DB in a Spock test - improved

def "Testing ordering of products - improved"() { given: "the creation of 3 new products" Sql sql = new Sql(dataSource) #A sql.execute("DELETE FROM PRODUCT") String insertProduct = "INSERT INTO PRODUCT (id,name,price, weight,stock) VALUES (?, ?,?,?,?);" #B sql.execute(insertProduct,[1, 'samsung',400,1,45]) #C sql.execute(insertProduct,[2, 'bravia',1200,3,2]) #C sql.execute(insertProduct,[3, 'canon',500,5,23]) #C when: "we read back the products" List<Product> allProducts = productLoader.getAllProducts(); then: "they should be ordered by name" allProducts.size() == 3 allProducts[0].name =="bravia" allProducts[1].name =="canon" allProducts[2].name =="samsung" cleanup: "remove inserted data" sql.execute("DELETE FROM PRODUCT") sql.close()}

#A Creation of Groovy SQL over an existing data source

#B Definition of a parameterized SQL statement

#C Running the same SQL statement with different parameters.

A final note regarding Groovy SQL is that if you use it in multiple test methods it is best to make it a @Shared field so that it is created only once, otherwise performance of your unit tests will suffer.

7.2.4 Integration testing with other containers (Java EE and Guice)

The example application I used in the previous paragraph was based on the Spring container simply because the Spring framework is very popular and mature among Java developers.

If you are not using Spring, chances are that your application is based on Java EE. In that case the respective facilities offered by Spring in integration tests, can be replicated using Arquillian[83], a test framework for Java EE applications that acts as a testing container and allowing access to EJBs, CDI [84] injection and other enterprise services.

Arquillian supports natively JUnit tests, but for Spock tests you need the Spock-Arquillian[85] extension. The extension has its own repository and a different lifecycle than Spock releases. It works by creating a special runner that brings the Arquillian facilities inside the Spock test.

Apart from Spring, the core Spock distribution also includes support for the Guice[86] dependency injection framework. In a similar manner, it allows you access Guice services/beans inside the Spock test.

If the dependency injection framework you use is something else (apart from Spring, Guice and Java CDI) and by the time you are reading this book there isn't a Spock extension for that you have two choices:

1. Manually initialize and inject your services in the Spock setupSpec() method.

2. Find a way to initialize the DI container programmatically inside the Spock test

The first option is not really practical because it means that you have to write a lot of boilerplate code normally not needed, going against the mentality of writing Spock tests in the first place (compact and readable tests).

The second way depends on the capabilities of the container you use and whether it supports declarative or programmatic configuration. As an example, assume that the Spock-Spring extension did not exist. The Spring container can be still created programmatically like this:

Listing 7.6 Manual Spring context creation

class ManualInjectionSpec extends spock.lang.Specification{ def "Testing hibernate mapping of product class - mem db"() { given: "a product DAO" ApplicationContext ctx = new #A ClassPathXmlApplicationContext("reduced-test-context.xml"); ProductLoader productLoader = ctx.getBean(ProductLoader.class) #B when: "we read products from the DB" List<Product> allProducts = productLoader.getAllProducts(); #C then: "the db is empty" allProducts.size() == 0 }}

#A Creates a Spring context from an XML file

#B Initializes manually a Spring bean

#C Using the Spring bean as before

This Spock test will still have access to the Spring context because it creates one manually. Notice the lack of any extra annotations in listing 7.6. Therefore, if your dependency injection framework supports programmatic initialization, you can still write Spock integration tests without the need of a special extension.

7.3 Functional testing of REST services with Spock

Moving up in the testing pyramid, we leave integration tests behind and reach functional tests. Functional tests view the whole system as a black box (in contrast with integration tests that deal with internal modules).

For non-interactive systems (i.e. those with no user visible component) functional testing involves the testing of the services they provide to the outside world. In practice this usually means testing the HTTP/REST[87] endpoints of the backend modules.

Figure 7.8 - A functional test sends a request and expects a certain response

REST services use JSON or XML for the transport format. My examples will be with JSON.

7.3.1 A simple REST service

A REST service is based on HTTP and a predefined message format (typically JSON or XML) and is implementation agnostic. Even though the application I use as an example is a Spring based one, it does not really matter to Spock. In fact, the application does not even have to be a Java one at all. You can use Spock if you want, to test the REST service of a Python or Ruby application.

The example application is REST API for the warehouse management example as already discussed in the previous sections. Here is an overview of the endpoint and operations it supports (all responses are in JSON format).

Table 7.2 HTTP endpoints of example application

Endpoint

GET

POST

PUT

DELETE

/status

Returns a success message ("up and running")

-

-

/products

Lists all products

Creates a default product

-

Deletes all products

/products/{id}

Returns a specific product

-

-

-

/products/{id}/name

-

-

Renames a product

-

Like all applications shown so far, this backend application was created for illustration purposes. The application uses Spring MVC for the implementation but this is completely irrelevant as far as functional tests are concerned. It could be implemented in any other framework or even programming language as long as it accepts JSON messages over HTTP endpoints.

7.3.2 Testing REST services using Java Libraries

Writing a Spock test for REST services is unsurprisingly very straightforward. You can use any REST client library that you are already familiar with. There are many[88] in the Java world and at least for Spock tests, you should choose the one that you feel is more readable and compact.

As a starting example I have selected the Spring Rest Template[89]. The first test just checks the /status endpoint (which returns a single string and not JSON).

Listing 7.7 Testing REST services with Spock and Spring RestTemplate

def "Simple status checker"() { when: "a rest call is performed to the status page" RestTemplate restTemplate = new RestTemplate() #A String status = restTemplate.getForObject("http://localhost:8080/rest- service-example/status", String.class) #B then: "the correct message is expected" status == "Up and Running" #C}

#A Creates a Spring Rest client

#B Performs a GET call on the /status endpoint

#C Examines the response of the REST call

The takeaway from this trivial example is that because of Groovy/Java compatibility, you can use any Java REST client library you already use in your JUnit tests. Spock can use it as well without any extra modifications. It is that simple!

7.3.3 Using the @Stepwise annotation to run tests in order

Now I am ready to create some additional tests for the business endpoints of my application. Here is the whole Spock specification.

Listing 7.8 Running multiple test methods in order

@Stepwise #Aclass SpringRestSpec extends Specification { def "Simple status checker"() { when: "a rest call is performed to the status page" RestTemplate restTemplate = new RestTemplate() String status = restTemplate.getForObject("http://localhost:8080/rest-service- example/status", String.class) then: "the correct message is expected" status == "Up and Running" } def "Cleaning all products"() { given: "a rest call is performed that deletes everything" RestTemplate restTemplate = new RestTemplate() restTemplate.delete("http://localhost:8080/rest-service- example/products") #B when: "a product list is requested" List<Product> products = restTemplate.getForObject("http://localhost:8080/rest- service-example/products", List.class) #C then: "it should be empty" products.size() == 0 } def "Creating a product"() { given: "a rest template" RestTemplate restTemplate = new RestTemplate() when: "a new product is created" Product product = restTemplate.postForObject("http://localhost:8080/rest- service-example/products","unused",Product.class) #D and: "product list is requested again" List<Product> products = restTemplate.getForObject("http://localhost:8080/rest- service-example/products", List.class) then: "it should have default values" with(product) #E { name == "A product" stock == 0 price == 0 weight == 0 } and: "product list should contain it" products.size() == 1 }}

#A Makes sure that all methods run in order

#B Performs a DELETE call on the /products endpoint

#C Performs a GET call on the /products endpoint

#D Performs a POST call on the products endpoint

#E Examines the JSON response

In listing 7.8 I have included test methods for the /products endpoint as well. The code should be familiar if you have ever worked with the Spring RestTemplate. There is nothing Spock specific inside the test methods. All code segments are Java statements that would work the same way in a JUnit test.

You should pay special attention however to the Stepwise annotation found at the top of the class. This is a Spock annotation that comes very handy and does two things:

1. It makes sure that Spock will run all test methods in the order they are defined in the Specification class

2. During run time, if any of the test methods fails, those that come after it will be skipped.

The purpose of the Stepwise annotation is to save you time when you have a large number of functional tests. While in theory all functional tests are independent, in practice this is rarely the case. For example, if the first test method fails (the one that checks the /status endpoint) it means that the test environment is probably down so there is no point in running any more tests.

The Stepwise annotation saves you time because you are informed right away when something fails and you can understand what problem is more easily than having all tests fail. Here is the runtime result with and without theStepwise annotation:

Figure 7.9 - The Stepwise annotation skips subsequent test methods after a failure.

With the Stepwise annotation enabled, I can instantly see in 2 seconds that the test environment is down instead of waiting for 4 seconds for all tests to run (and fail). In a real enterprise project with hundreds of functional tests that may take several minutes (or even hours) the Stepwise annotation is a life saver as it drastically cuts the time of developer feedback after a failed build.

7.3.4 Testing REST services using Groovy RESTClient

As with integration tests, the advantage of using Spock is that you are not constrained to Java libraries, but you can also use Groovy utilities. As an example, an alternative Rest client[90] can be used instead of the Spring Rest Template.

Here is the same test of listing 7.8, this time using the Groovy Rest Client:

Listing 7.9 Using Groovy Rest Client in a Spock test

@Stepwise #Aclass GroovyRestClientSpec extends Specification { @Shared def client = new RESTClient("http://localhost:8080/rest-service- example/") #B def "Simple status checker"() { when: "a rest call is performed to the status page" def response = client.get(path : "status") #C then: "the correct message is expected" with(response) { data.text == "Up and Running" #D status == 200 #E } } def "Cleaning all products"() { given: "a rest call is performed that deletes everything" client.delete(path : "products") #F when: "a product list is requested" def response = client.get(path : "products") then: "it should be empty" with(response) { data.isEmpty() status == 200 } } def "Creating a product"() { when: "a new product is created" def response = client.post(path : "products") #G and: "product list is requested again" def listResponse = client.get(path : "products") then: "it should have default values" with(response) { data.name == "A product" data.stock == 0 data.price == 0 status == 200 } and: "product list should contain it" listResponse.data.size() == 1 }}

#A Makes sure that all methods run in order

#B Creates a Rest client

#C Performs a GET call on the /status endpoint

#D Examines the text response

#E Examines http error code

#F Performs a DELETE call on the /products endpoint

#G Performs a POST call on the /products endpoint

As you can see the code is mostly the same. For each method call, I also check the HTTP error code, as it is very easy to verify it with the REST Client. As an exercise feel free to write a functional test for the other endpoints of the application (i.e. the calls for renaming an existing product). The Groovy REST client has many more facilities not shown above, that might be helpful in your own application should you choose to use it.

7.4 Functional testing of Web applications with Spock

The previous section covered functional tests for backend Java applications that are not interactive. In this section I will show you how you can test frontend applications that sport a Web interface accessible via the browser.

For these kinds of tests you need a way to control the browser and replicate the actions (e.g. fill forms, click buttons) that a human user normally performs. Spock does not have built-in support for this and instead collaborates with Geb[91], the Groovy browser automation library.

7.4.1 Browser Automation with Geb

Geb is a library that provides a Groovy abstraction on top of the popular Selenium/Webdriver[92] framework for automating a browser. If you have ever worked with Selenium you already know what Geb does.

What Geb brings to the table is excellent integration[93] with Spock and also a jQuery[94] like language for accessing web page content. If you already know jQuery (or any other similar CSS selector syntax for that matter) then Geb will be very familiar to you.

As an quick example if you want to examine the text for the h2 header in a web page, Geb allows you to write:

$("h2").text()

If you want to click the button with an id myButton Geb offers you this:

$("#myButton").click()

With Geb you essentially reuse your knowledge of jQuery. If you are not familiar with jQuery then you need to examine its documentation and especially the part for CSS selectors in order to fully utilize Geb.

7.4.2 The example web application

The application we will test with Spock and Geb is a simple Web interface over the warehouse manager we have seen in the previous examples. Here is a sample screen from this application:

Figure 7.10 Web interface that will be used for Spock tests.

The code is using Spring MVC, but in a similar manner to the REST tests, the implementation technology does not really matter. Geb only interacts with the final web page and it doesn't care for the underlying technology. You could write Spock/Geb tests for a PHP application if you wished using the same CSS selectors.

7.4.3 Spock and Geb - a match made in heaven

Let's start with a very simple example of Spock and Geb together. As a first test we will just verify the title of the first page of the application. Here is the expected result:

Figure 7.11 Expected result for title page is the string "Spock/Geb Web example"

And here is the Geb specification that tests this:

Listing 7.10 Using Geb and Spock together

class HomePageSpec extends GebSpec { #A def "Trivial Geb test for homepage"() { when: "I go to homepage" Browser.drive { #B go "http://localhost:8080/web-ui-example/index.html" } then: "First page should load" // make sure we actually got to the page title == "Spock/Geb Web example" #C } }

#A Spock Specification class that makes Geb facilities available

#B Orders the test browser to load a specific URL

#C Test the title of the application

The most important thing to notice in listing 7.10 is that the test class extends the GebSpec class and not the Spock Specification as shown in all examples so far. This is essential so that Geb methods and objects are available inside the Spock methods.

Once this is done, I use the Browser object to load the first page of the application. Finally I examine the title object. The title object is an implicit one offered by Geb and always represents the html title of the current HTML page. It does not follow the jQuery pattern because it is not part of the content of the page.

Will this test actually launch a browser?

Remember that Geb is really an abstraction over Selenium/Webdriver so it supports whatever browser implementations are already there. In the source code of the book the default browser is Firefox, so if you run this test a new Firefox instance will be launched on your computer and you will see it react automatically to the test definitions. You can use other browsers or even browser emulators (such as Phantom.js- http://phantomjs.org/) as other options. Consult the Geb documentation on how to achieve this.

To see the jQuery syntax of Geb, let's modify our test to look at the page content in addition to the page title. We will test an HTML header (h1) and also make sure that the first tab of the user interface is selected. Here is the expected result:

Figure 7.12 HTML content that will be verified by the Geb test. We will verify the h1 element and the "active" CSS class.

The updated Spock test verifies the title as before and also reads the page content to make sure that the expected text is present on the page.

Listing 7.11 Using Geb to access page content

def "Trivial Geb test for homepage -header check"() { when: "I go to homepage" Browser.drive { go "http://localhost:8080/web-ui-example/index.html" #A } then: "First page should load" title == "Spock/Geb Web example" #B $("h1").text() == "Java Testing with Spock - Sample code" #C $(".active").text() == "Welcome" #D}

#A launches the first page of the application in the browser

#B Examines the title of the page

#C Examines the content of the h1 element

#D Examines the content of the element with the "active" css class

Listing 7.11 demonstrates the jQuery like style of Geb for accessing page content. The last two lines in the then: block will be examined by Geb against the HTML content found in the browser. The test will fail if the HTML content differs from the expected one.

7.4.4 Using Geb to interact with a web page

For a more useful example than simple page loading, let's see how you can emulate user actions in a web page. The sample application contains a form that allows the user to create a new product. For that purpose an HTML form is used to define the name of the product and its price. Once the user submits the form, a success message appears.

Figure 7.13 Details of an HTML form. We will fill the input fields and submit it programmatically

We will create a test that navigates to the form page, inputs the name of the product, submits the form and verifies the success message (not shown in figure 7.14). Here is the code:

Listing 7.12 Using Geb to submit HTML forms

@Stepwise #Aclass AddProductGebSpec extends GebSpec { #B def "Navigation to page"() { when: "I go to the new product page" Browser.drive { go "http://localhost:8080/web-ui-example/add- product.html" #C } then: "the form should load" $(".col1").$("h2").text() == "New Product details" #D } def "Creation of new product"() { when: "I fill in product details" $("input[name='productName']").value("Bravia TV") #E $("#createProductButton").click() #F then: "I should see a success message" $(".ok").text() == "You added new product named: Bravia TV." #G } }

#A Ensures that test methods will run in order

#B This Spock test has access to Geb facilities

#C Navigates to the page with the html form

#D Verifies that browser is in correct page

#E Enters text into an input field

#F Activates the form button

#G Verifies the success message shown on page

There are several important points in listing 7.12. First of all I have used the Stepwise annotation again. The reason for this is that the test contains two methods. The first one navigates to the HTML form page, and the second submits the form. If the first fails for some reason (e.g. the application is not up) then there is no point in running the second method. The Stepwise annotation ensures the form won't be submitted if its page cannot be found.

Secondly, in order to verify the formed page aI use an HTML element chain:

$(".col1").$("h2").text() == "New Product details"

This line means "locate an element with the CSS class col1 and then search for a child that is a header of level 2. This header should contain the text New product details".

Once that is done, the form is submitted with the following two lines:

$("input[name='productName']").value("Bravia TV")$("#createProductButton").click()

The first line means "locate an HTML element of type input that has a name attribute with value productName. Once that is found fill in the text Bravia TV". The second line says "find an element with id createProductButton. Then click it (assuming that it is a button)"

Running the test will actually launch the Firefox browser on your computer and you will see it perform these actions in real time. The final line in the then: block locates an element with CSS class ok and checks its text (in the example application it is a span HTML element).

I hope that this example will give you an idea on the capabilities of Geb. I have barely scratched the surface of all the possible use cases. Check the official Geb documentation[95] for more details. Make sure not to miss the Page Objects pattern[96] for reducing[97] duplicated code among tests and also the ability to get screenshots[98] while a test runs.

As an exercise, try to write Geb tests for the page of the application that lists existing products. Write a test that also fills in the price field of the form and then goes to the inventory page and verifies that the product is correctly inserted with the correct price

7.5 Running Spock tests as part of a build process

So far I have silently assumed that whenever I show you a Spock test you run it manually yourself and check visually the results in the IDE or the command line shell. While this is true for your day-to-day development schedule, a well-designed enterprise application employs a build server that automatically checks-out code at various time intervals, compiles it, runs unit tests and creates reports in a completely automated manner.

If you are not familiar with build servers, explaining them here is outside of the scope of this book. As a suggestion start by downloading Jenkins[99] and then read both the theory[100] and practice[101] behind a sound build process.

For the rest of the chapter, I will assume that you already have a build server in place for running JUnit tests and will only mention what you need to do for Spock (spoiler: almost nothing as Spock is JUnit compatible).

7.5.1 Splitting unit, integration and functional tests

If you look back at table 7.1 where I list the characteristics of unit, integration and functional tests, it should be clear that they have different requirements.

For starters, functional (and sometimes integration) tests require a running replica of the system that is tested. This means that at least functional tests must be treated differently than the rest of the tests.

Another big difference is the speed of tests. Unit tests (that depend only on Java code) are very fast and give quick feedback. Integration and functional tests are much slower (especially when external systems and real databases are involved).

The speed of unit tests means that they can be executed automatically after every developer commit for quick feedback. Functional tests on the other hand may run less frequently (e.g. once a day) and also require the setup of a test environment exclusive to them (which typically replicates the production environment)

These best practices are not specific to Spock. They also apply to JUnit or TestNG. I am mentioning them here so that before complaining that "Geb tests are really slow", you should understand that Geb tests should run in a different manner than simpler Spock tests.

In the sample code of the book, I use Maven and have chosen to launch the Tomcat application server before the functional tests run. Here is the Maven lifecycle[102] for the examples of this chapter:

Figure 7.14 Tomcat is launched before functional tests and shuts down afterwards

With this approach there is a split between slow and fast tests. Running mvn test will only run the fast unit tests, and running mvn verify will also run the slow functional tests (after launching a Tomcat instance). This lifecycle is accomplished by using the Maven failsafe[103] plugin and the Tomcat plugin[104] as shown below:

Listing 7.13 Running Spock functional tests on a Tomcat instance

[...rest of pom.xml....]<build> <plugins> [...rest of build plugins....] <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-failsafe-plugin</artifactId> <version>2.18</version> <executions> <execution> <goals> <goal>integration-test</goal> #A <goal>verify</goal> </goals> </execution> </executions> <configuration> <useFile>false</useFile> <includes> <include>**/*Spec.java</include> #B </includes> </configuration> </plugin> <plugin> <groupId>org.apache.tomcat.maven</groupId> <artifactId>tomcat7-maven-plugin</artifactId> <version>2.2</version> <executions> <execution> <id>tomcat-run</id> <goals> <goal>run-war-only</goal> </goals> <phase>pre-integration-test</phase> #C <configuration> <fork>true</fork> </configuration> </execution> <execution> <id>tomcat-shutdown</id> <goals> <goal>shutdown</goal> </goals> <phase>post-integration-test</phase> #D </execution> </executions> </plugin> </plugins></build>

#A Instructs failsafe plugin to run Spock tests in integration-test phase.

#B Naming convention for Spock tests that will run as integration-test phase

#C Starts tomcat before Spock tests run

#D Stops tomcat after Spock tests run

This technique works for simple to medium size applications. For large scale enterprise applications that need specialized test environments you would need to adapt your build system according to your business requirements in cooperation with the team responsible for provisioning[105].

Running both Spock and JUnit tests in the same Java project

If it isn't clear by now, the Maven plugins (surefire and failsafe) will run both JUnit and Spock tests in a similar manner. There is no special configuration needed if you have both kinds of tests. You can mix and match. Many configurations are possible. For example, you could have JUnit tests run as pure unit tests and use Spock only for Web tests (with Geb). Consult the Maven documentation for the respective plugins and the appendix of this book for more information on the subject.

7.5.2 Getting code coverage from Spock tests

For some strange reason, when I introduce Spock to Java developers, even after I explain that it uses the JUnit runner, the first question they ask is how one can obtain code coverage statistics with Spock.

The answer to this question is of course: "in the same way as you get coverage reports[106] for JUnit". There is nothing special about it. Here is a sample JaCoCo[107] report that was generated by Spock tests:

Figure 7.15 Code coverage by Spock tests

There is nothing Spock specific about this report. I obtained it by adding JaCoCo in my pom.xml file and executing the jacoco:report goal with Maven as I would for JUnit.

Listing 7.14 Using JaCoCo with Spock

[...rest of build plugins here...]<plugin> <groupId>org.jacoco</groupId> <artifactId>jacoco-maven-plugin</artifactId> <version>0.7.4.201502262128</version> <executions> <execution> <id>prepare-agent</id> <goals> <goal>prepare-agent</goal> </goals> </execution> </executions></plugin> &nbsp.[...rest of pom.xml here...]

The same principle applies to any other tools that you have around JUnit. If they work fine with JUnit they will probably work with Spock as well. For a full-blown code quality reporting tool you should also look at SonarCube[108] if you aren't already using it.

Using Spock with SonarCube requires exactly zero extra configuration (apart from the standard instructions[109]).

Figure 7.16 Code coverage from SonarCube after Spock tests run.

I hope that it should be clear to you now the level of compatibility between JUnit enabled tools and Spock tests.

7.6 Summary

· Unit tests focus on a single class. Integration tests focus on a module. Functional tests focus on the whole application

· Unit/Integration/Functional tests have different characteristics and constraints. They should be handled differently

· According to the testing pyramid as a rule of thumb 70% of total tests should be pure unit tests, 20% should be slower integration tests and 10% should be even slower functional tests.

· Spock supports both integration and functional tests (as well as pure unit tests as already shown in the previous chapters)

· Spock will automatically load a Spring context if the Specification class is annotated with the Spring ContextConfiguration annotation.

· Inside a Spring-enabled Spock test, all normal test facilities from Spring are available (including transactions)

· A good practice is using a separate Spring context just for tests. It should not contain classes unrelated to testing and it should replace slow services and databases with mocked ones or in-memory implementations respectively

· Groovy SQL can be used to directly access the Database as an alternative to existing Java solutions

· Spock supports Guice tests via a built-in extension. Spock also supports Arquillian tests via an external extension

· Spock can test REST services using the existing Java client REST libraries.

· An alternative to Java REST client libraries is the Groovy RESTClient library

· The Stepwise annotation can be used in Spock tests with multiple test methods to ensure correct ordering of the method.

· All methods that come after a failed one will be skipped by Spock allowing for faster developer feedback if the Stepwise annotation is used.

· Geb is a browser automation library that uses Webdriver/Selenium and offers a jQuery like syntax for accessing page content

· Spock and Geb can work together to create Web related functional tests.

· Geb facilities are possible if a test extends the GebSpec class instead of the standard Spock Specification

· Geb can direct the browser, fill in forms, click buttons and generally mimic a human user interacting with a browser

· Spock unit/integration/functional tests should be handled differently inside the build process mainly because of different time constraints.

· One can use the Maven failsafe and Tomcat plugins to run Spock functional tests with a live application.

· Running both JUnit and Spock tests is possible without any special configuration.

· Getting coverage reports from Spock tests is exactly the same as getting coverage reports from JUnit (using JaCoCo)

· Spock is compatible with the SonarCube Quality dashboard out of the box.

[65] http://www.gebish.org/

[66] For more information see the book "Test Driven" also by Manning.

[67] Or perform crash tests with dummies which is much more fun.

[68] Codebase is 500K lines of code, team of 20 people, dedicated QA department, requirements that resemble a small book when printed, you get the picture.

[69] http://googletesting.blogspot.co.uk/2015/04/just-say-no-to-more-end-to-end-tests.html

[70] https://en.wikipedia.org/wiki/Black-box_testing

[71] https://spring.io/

[72] Using Arquillian - http://arquillian.org/

[73] https://github.com/google/guice

[74] https://github.com/kkapelon/java-testing-with-spock/tree/master/chapter7

[75] http://hsqldb.org/

[76] and also the @SpringApplicationConfiguration annotation from Spring boot.

[77] https://spring.io/docs

[78] Actually the default behavior by Spring is to revert all transactions. I am showing the Rollback annotation for emphasis only

[79] http://www.h2database.com/html/main.html

[80] https://github.com/kkapelon/java-testing-with-spock/blob/master/chapter7/spring-standalone-swing/src/test/resources/reduced-test-context.xml

[81] JUnit tests need the special SpringJUnit4ClassRunner in order to access Spring beans

[82] http://docs.groovy-lang.org/latest/html/api/groovy/sql/Sql.html

[83] http://arquillian.org/

[84] The Java Spec for Dependency injection

[85] https://github.com/arquillian/arquillian-testrunner-spock

[86] https://github.com/google/guice

[87] https://en.wikipedia.org/wiki/Representational_state_transfer

[88] Such as Resteasy(http://resteasy.jboss.org/), Jersey(https://jersey.java.net/) or Restlet (http://restlet.com/).

[89] https://spring.io/guides/gs/consuming-rest/

[90] https://github.com/jgritman/httpbuilder/wiki/RESTClient

[91] http://www.gebish.org/

[92] http://www.seleniumhq.org/

[93] Geb is written by Luke Daley who is also a Spock committer

[94] https://jquery.com/

[95] http://www.gebish.org/manual/current/reporting.html

[96] http://docs.seleniumhq.org/docs/06_test_design_considerations.jsp#page-object-design-pattern

[97] http://www.gebish.org/pages

[98] http://www.gebish.org/manual/current/reporting.html

[99] https://jenkins-ci.org/

[100] http://martinfowler.com/books/continuousDelivery.html

[101] http://www.wakaleo.com/books/jenkins-the-definitive-guide

[102] https://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html

[103] https://maven.apache.org/surefire/maven-failsafe-plugin/

[104] http://tomcat.apache.org/maven-plugin.html

[105] I hear they are called "devops" these days.

[106] Common coverage tools are Cobertura (http://cobertura.github.io/cobertura/) and Clover (https://www.atlassian.com/software/clover/).

[107] http://www.eclemma.org/jacoco/

[108] http://www.sonarqube.org/

[109] http://www.manning.com/papapetrou/