The previous part of this tutorial described the structure of a feature method and helped us to specify the expected behavior of the system under specification.

This time we will take a closer look at the *where* block that is used to provide input data for our feature methods when we are writing parameterized tests with Spock Framework.

Let's get started.

**Additional Reading:**

If you are not familiar with Spock Framework, **you should read** the following blog posts before you continue reading this blog post:

- Writing Unit Tests With Spock Framework: Creating a Maven Project describes how you can create a Maven project that runs unit tests which use Spock Framework.
- Writing Unit Tests With Spock Framework: Creating a Gradle Project describes how you can create a Gradle project that runs unit tests which use Spock Framework.
- Writing Unit Tests With Spock Framework: Introduction to Specifications, Part One provides an introduction to Spock specifications, helps you to write your first specification, and describes the structure of a specification.
- Writing Unit Tests With Spock Framework: Introduction to Specifications, Part Two describes the structure of a feature method and helps you to specify the expected behavior of the system under specification.

## Writing Parameterized Tests With Spock Framework

Let's assume that we had to specify the expected behavior of the *Math* class' *max(int a, int b)* method. Its Javadoc states that it:

Returns the greater of two int values. That is, the result is the argument closer to the value of

Integer.MAX_VALUE. If the arguments have the same value, the result is that same value.

The source code of our (a bit naive) specification class looks as follows:

import spock.lang.Specification class MathSpec extends Specification { def "Get the max value of two numbers (without parameters)"() { expect: 'Should return the bigger number' Math.max(1, 0) == 1 Math.max(2, 3) == 3 } }

*expect*block because we are specifying the expected behavior of a method that has no side effects.

Let's find out how we can rewrite this feature method by using data driven testing support of Spock Framework.

### Rewriting the Expect Block

The first thing that we have to is to rewrite the *expect* block of our feature method. We can do this by following these steps:

**First**, we have to replace the hard coded int values with the "data variables" *a*, *b*, and *c*. These data variables are described in the following:

- The
*a*and*b*data variables are the method parameters which are passed to the*max()*method of the*Math*class. - The
*c*data variable is the expected value that is returned by the*Math*class'*max()*method.

**Second**, we have to specify the expected behavior of the *Math* class' *max()* method by using these data variables.

The source code of our rewritten feature method looks as follows:

import spock.lang.Specification class MathSpec extends Specification { def "Get the max value of two numbers"() { expect: 'Should return the bigger number' Math.max(a, b) == c } }

**Additional Reading:**

After we have rewritten the *expect* block of our feature method to use data variables, we have to provide the input data for our feature method. Let's find out how we can provide the input data by using so called data pipes.

### Providing Input Data by Using Data Pipes

We can provide the input data for our feature method by following these steps:

- Add a new
*where*block into our feature method. - Configure the values of each data variable by following these steps:
- Connect the data variable
*a*with a data provider that contains the*int*values: 1 and 2. - Connect the data variable
*b*with a data provider that contains the*int*values: 0 and 3. - Connect the data variable
*c*with a data provider that contains the*int*values: 1 and 3.

- Connect the data variable

The source code of our specification class looks as follows:

import spock.lang.Specification class MathSpec extends Specification { def "Get the max value of two numbers"() { expect: 'Should return the bigger number' Math.max(a, b) == c where: a << [1,2] b << [0,3] c << [1,3] } }

**Additional Reading:**

Although our *where* block is completely functional, it is not very readable. We can make it a lot more readable by using data tables.

### Providing Input Data by Using Data Tables

We can create a data table by following these rules:

- The first line of the data table declares the data variables.
- The subsequent table rows are called data rows. These data rows contains the values of data variables that are passed to our feature method, and our feature method is invoked once per a data row.
- The different column values of a table row are separated by using the pipe character ('|').

After we have replaced our old *where* block with a *where* block that provides the input data by using data tables, the source code of our specification class looks as follows:

import spock.lang.Specification class MathSpec extends Specification { def "Get the max value of two numbers"() { expect: 'Should return the bigger number' Math.max(a, b) == c where: a | b | c 1 | 0 | 1 2 | 3 | 3 } }

Although our new *where* block is a lot cleaner than the *where* block which uses data pipes, we can make it a bit better by separating the input values and the expected output value(s) with a double pipe symbol ('||'). After we have done this, the source code of our specification class looks as follows:

import spock.lang.Specification class MathSpec extends Specification { def "Get the max value of two numbers"() { expect: 'Should return the bigger number' Math.max(a, b) == c where: a | b || c 1 | 0 || 1 2 | 3 || 3 } }

**Additional Reading:**

Let's summarize what we have learned from this blog post.

## Summary

This blog post has taught us three things:

- We can specify the input values and the expected output values by using data variables.
- We can provide input data for our feature methods by adding a
*where*block into our feature method and using either data pipes or data tables. - Providing input data by using data tables is a lot cleaner than using data pipes.

The next part of this tutorial describes how we can create test doubles with Spock Framework.

**P.S.** You can get the example application of this blog post from Github.

In JUnit, multiple test cases can be executed in a loop with: @RunWith(Parameterized.class)

How can this be achieved in Spock?

I mean if you have multiple def for a single test, how you can loop with different sets of input data?

Using where block in a def only iterates inside itself.

Hi,

Check out this blog post. It explains how you can write parameterized tests with Spock Framework (it covers both data pipes and data tables).

I know about data pipes and data tables. This concepts are for SINGLE "def" EXECUTION.

I need to to about how to execute multiple defs as a unit test hence how to provide input data for that?

Unfortunately I don't know if it is possible to create an input data set that is automatically used by multiple feature methods.

Hi,

You mentioned "The next part of this tutorial describes how we can create test doubles with Spock Framework." But I do not find any link to the next part four.

Hi,

There is no link to next part since I haven't written it :( I might continue writing this tutorial at some point if people think that this tutorial is valuable to them.