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.

Related Blog Posts
Natively Compiled Java on Google App Engine
Google App Engine is a platform-as-a-service product that is marketed as a way to get your applications into the cloud without necessarily knowing all of the infrastructure bits and pieces to do so. Google App […]
Building Better Data Visualization Experiences: Part 2 of 2
If you don't have a Ph.D. in data science, the raw data might be difficult to comprehend. This is where data visualization comes in.
Unleashing Feature Flags onto Kafka Consumers
Feature flags are a tool to strategically enable or disable functionality at runtime. They are often used to drive different user experiences but can also be useful in real-time data systems. In this post, we’ll […]
A security model for developers
Software security is more important than ever, but developing secure applications is more confusing than ever. TLS, mTLS, RBAC, SAML, OAUTH, OWASP, GDPR, SASL, RSA, JWT, cookie, attack vector, DDoS, firewall, VPN, security groups, exploit, […]