5.3. Using data pipes for calculating input/output parameters

Data tables should be your bread and butter when writing Spock parameterized tests. They shine when all input and output parameters are known in advance and thus can be embedded directly in the source code.

But sometimes the test parameters are computed on the spot or come from an external source (typically a file, as you’ll see later in this chapter). For those cases, using data pipes is a better option. Data pipes are a lower-level construct of Spock parameterized tests that can be used when you want to dynamically create/read test parameters.[8]

8

Data tables can be seen as an abstraction over data pipes.

As a first example, let’s rewrite the first data table code of listing 5.1, using data pipes this time. The result is shown in the next listing.

Listing 5.13. Trivial example of data pipes

The code accomplishes the same thing as listing 5.1. But this time the tabular format is “rotated” 90 degrees. Each line of the where: block contains a parameter, and the scenarios of the test are the imaginary columns. The key point here is the use of the left-shift operator symbol (<<). In the context of the where: block, it means, “For the first scenario, pick the first value in the list for the input and output parameter; for the second scenario, pick the second value in the list, and so on.”

In this example, I pass both input and output parameters in a list. But the left-shift operator can work on several other things, such as iterables, iterations, enumerations, other collections, and even strings. You’ll examine the most common cases in the next sections.

5.3.1. Dynamically generated parameters

If you compared listing 5.13 to listing 5.2, you’d be right to say that there’s no real advantage to using data pipes. That’s because in that particular scenario, all parameters are known in advance and can be embedded directly in their full form. The power of data pipes becomes evident with computed data.

In the next listing, let’s consider a different example, in which using a data table would be impractical because of the sheer size of input and output parameters.

Listing 5.14. Using Groovy ranges as data generators

The (M..N) notation is a Groovy range. It’s similar to a list that will contain all values, starting from M and ending in N. Thus the (20..80) notation indicates a range of all integers from 20 to 80. Groovy expands the ranges and Spock picks each value in turn, resulting in a parameterized test with 60 scenarios. You can see the scenarios in detail if you run the unit test, as shown in figure 5.12.

Figure 5.12. Using ranges to automatically generate 60 scenarios instead of creating a data table with 60 lines.

Creating a data table with 120 values would make the unit test unreadable. By using data pipes and Groovy ranges, you’ve created 60 scenarios on the spot, while the source code only contains two statements (the ranges).

For a more realistic example, assume that you want to write an additional unit test for the ImageValidator class that ensures that all JPEG images are considered valid regardless of capitalization (anywhere in the name or the extension). Again, embedding all possible combinations in a data table would be time-consuming and error-prone.

You can calculate several possible variations with some Groovy magic, as shown in the following listing.

Listing 5.15. Using Groovy combinations

The where: block contains a single statement. If you run the unit test, you’ll see that this statement creates 72 scenarios (from 3 × 2 × 2 × 3 × 2 strings), as shown in figure 5.13.

Figure 5.13. Creating 72 unit test runs from a single Groovy statement

The code works as follows: The combinations() method takes the variations of the word sample, the letters J, P, E, and G, and creates a new collection that contains all possible variations as collections themselves. The input parameter is a string. To convert each individual collection to a string, I call the join() method, which automatically creates a single string from a collection of strings. Because I want to do this with all collections, I use the star-dot Groovy operator (*.), which applies the join() method to all of them.

If your head is spinning at this point, don’t worry! It took me a while to write this statement, and as you gain more Groovy expertise, you’ll be able to write Groovy one-liners as well. The example is supposed to impress you, but don’t be distracted by the core lesson here, which is the flexibility of Spock data pipes.

5.3.2. Parameters that stay constant

In all examples of parameterized tests I’ve shown you so far, the parameters are different for each scenario. But at times, one or more parameters are constant. Spock allows you to use direct assignments if you want to indicate that a parameter is the same for each scenario. Instead of the left-shift operator, you use the standard assignment operator, as shown in the following listing.

Listing 5.16. Constant parameters in Spock tests

The scenarios used for listing 5.16 are [20, -1], then [34, -1], [44, -1], and finally [67, -1]. I admit that the example isn’t enticing. I needed to show it to you as a stepping stone to the true use of the assignment operator in the where: block—derived variables.

5.3.3. Parameters that depend on other parameters

You’ve seen how the assignment operator is used for constant variables in listing 5.16. What’s not evident from the listing is that you can also refer to other variables in the definition of a variable.

In the next listing, the second parameter of the test is based on the first.

Listing 5.17. Derived parameters in Spock tests

Running this test shows how the second parameter is recalculated for each scenario according to the value of the first, as shown in figure 5.14.

Figure 5.14. Derived values are recalculated for each test run. Here the second parameter is always the negative representation of the first one.

This technique allows you to have variables that are dynamically generated based on the context of the current scenario.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.190.156.93