Mar 18, 2013

Testing tabular output in Spock

On my current project, we’ve created a large suite of Fitnesse tests.  These tests work quite well for validating certain types of data that are messy and difficult to visualize in normal unit tests.  For example, if I want to test a function that returns a list of payments, we can write a simple table in the wiki to validate that entire list.  We are not using most of the other features that Fitnesse was designed for however.  The wiki format is nice, but firing up a server and a full application to test against is not really what we’re going for in most cases.  Developers are the only ones who look at these tests so there is no reason for the wiki interface that Fitnesse provides.  Forcing all of our setup code into fixtures is an unnecessary complication that adds extra maintenance.

Since our primary testing framework is Spock, and Spock has a great data table syntax, I thought it would be the perfect fit for these tests.  I’d just move the tables over, convert some fixtures to helper functions and we’d have one less testing framework to maintain.

What I failed to think about initially is that Spock data tables are fundamentally different from Fitnesse query fixtures.  While query fixtures are designed to output a list of data and validate the entire list, Spock data tables validate one row against an execution multiple times.  What Spock does is what you want the vast majority of the time, but there are cases, like the one I mentioned above, where you want to validate a list of data returned by an execution.  In these cases, a data table-like syntax is very nice to easily visualize what you’re validating.

Here are a few examples of how I approached this.  Let’s say I have a function I’m testing that returns a list of dates and payment amounts.  My expected output is a list of Payment objects.  I want to validate the date and amount on each one of these objects.  Using Spock without any data tables would look something like:

setup: 
//...

when:
def results = myClass.getPayments()

then:
results[0].date == '2013-01-01'
results[0].amount == 100.00
results[1].date == '2013-02-01'
results[1].amount == 150.00
//...etc

That works, but it’s kind of busy, and if you start adding other values to that object it gets messy very fast.  What if I try to use data tables?

setup:
//...

when:
def results = myClass.getPayments()

then:
results[idx].date == date
results[idx].amount == amount

where:
idx | date         | amount
0   | '2013-01-01' | 100.00
1   | '2013-02-01' | 150.00
//...etc

That certainly is a lot more readable.  If I start to add other values to the object I just add some more columns and it will still be relatively easy to follow.  There’s a huge problem here though.  In this test I run the code under test for every iteration. That’s a lot of extra work just to get a nicer format for my test.

My solution to this issue was to create a simple Spock extension.  You can find it at https://github.com/sjurgemeyer/spock-extensions.  This extension provides a new annotation called SingleExecution, which will only run the specified code once so that you can validate multiple rows against it.  The syntax is still not quite perfect, but it’s a big improvement over the first example above and avoids the multiple executions of the second example.

@SingleExecution ('calculatePayments')
def "Should have implicit result field available for all tests"() {
when: //result is implicitly created by the annotation
def row = result[idx]

then:
row.date == date
row.amount == amount

where:
idx | date         | amount
0   | '2013-01-01' | 100.00
1   | '2013-02-01' | 150.00

//This closure gets called one time, regardless of the number of rows in the where clause
def calculatePayments = {
    //...
    return myClass.getPayments()
}

Admittedly, this is working around the framework a little bit, but it does provide a clean way to test tabular data returned from a single execution.  There are many situations, especially when doing financial calculations where this makes testing much easier.

About the Author

Object Partners profile.

One thought on “Testing tabular output in Spock

  1. Kanti Patel says:

    How to use @SingleExecution extesion with @DbUnit for tearDown operation DatabaseOperation.DELETE?

Leave a Reply

Your email address will not be published. Required fields are marked *

Related Blog Posts
Google Professional Machine Learning Engineer Exam 2021
Exam Description A Professional Machine Learning Engineer designs, builds, and productionizes ML models to solve business challenges using Google Cloud technologies and knowledge of proven ML models and techniques. The ML Engineer is proficient in all aspects […]
Designing Kubernetes Controllers
There has been some excellent online discussion lately around Kubernetes controllers, highlighted by an excellent Speakerdeck presentation assembled by Tim Hockin. What I’d like to do in this post is explore some of the implications […]
React Server Components
The React Team recently announced new work they are doing on React Server Components, a new way of rendering React components. The goal is to create smaller bundle sizes, speed up render time, and prevent […]
Jolt custom java transform
Jolt is a JSON to JSON transformation library where the transform is defined in JSON. It’s really good at reorganizing the json data and massaging it into the output JSON you need. Sometimes, you just […]