Monday, 10 October 2011

Making Spanish Omelets with Spock

Oh man I really had fun making this entry. I discovered Spock this year at gr8conf, and I really liked it.

Spock is awesome to do testing. It's really easy to think how to create new tests. Most of the times you have to deal with tests you don't even know what they were for, and you can't figure it out because the name doesn't help either. I usually code on Eclipse and It's really helpful to take a look on the test execution and see the description of the failed test.

I'm revisiting Spock and I've started with a funny and simple case: How to cook spanish omelets.


First of all we have two domain classes SpanishOmelet which is going to hold all the ingredients needed, and SpanishChef who could be anyone cooking the omelets.

package org.spockframework.basics.dotop

class SpanishOmelet {

def peopleEating = 2
def duration = 20
def eggs = 2
def onions = 0.5
def potatoes = 2
def finish = 'raw'

package org.spockframework.basics.dotop

class SpanishChef {

def finish = 'well done'

def cooks = {omelet->
omelet.finish = finish

So, my first Spock specification is to make an omelet myself. Let's go.

package org.spockframework.basics.dotop

import spock.lang.Specification;

class SpanishOmeletSpecification extends Specification{

def "This is the way we do spanish omelet at home"(){
setup: 'I usually like it well done'
def spanishOmelet = new SpanishOmelet()
def spanishCooking = new SpanishChef(finish:'well done')
expect: 'Ingredients for two people'
eggs == 2
onions == 0.5
potatoes == 2
peopleEating == 2
when: 'I cook it'
spanishCooking.cooks spanishOmelet
then: 'It ends a little bit crunchy'
spanishOmelet.finish == 'well done'

  • First we create our class extending org.spockframework.Specification
  • Then we create our first test calling it in a very descriptive way "This is the way we do spanish omelet at home". In Java it would be the name of a method, and no matter how good the name could be, It won't ever be as descriptive as this one is.
Then we have 4 different blocks to build our specification
  • setup: It is supposed to be used for variables used maybe in several blocks of the specification
  • expect: It's like a check list of things you have to check before moving on. in this case, we expect for example to have two eggs for each omelet before getting started. I we don't have the ingredients, poor us!
  • when: This indicates action, when something happens. In this case, when we cook, something is going to happen, something eatable, I hope.
  • then: The conclusion, the outcome. Here you can check the things you've done. Here I hope to have made a crunchy spanish omelet.
But I feel greedy today, and I'm wondering what It takes to make spanish omelets for 5000 people.

Let's view the specification:

package org.spockframework.basics.dotop

import spock.lang.Specification;

class SpanishOmeletGuinessWorldRecord extends Specification{

def "Cooking spanish omelets for more than a month"(){
setup: 'Get ingredients for almost 5000 people'
def ingredients = []
def oneSingleChef = new SpanishChef()
ingredients << new SpanishOmelet()
when: 'We finish cooking'
ingredients.each oneSingleChef.cooks
then: "We'll have"
ingredients*.potatoes.sum() == 5000
ingredients*.eggs.sum() == 5000
ingredients*.onions.sum() == 1250
ingredients*.peopleEating.sum() == 5000
ingredients*.finish.unique().size() == 1
ingredients*.duration.sum() == 50000

The same thing that before. I have a nice description instead an unreadable method name, and I start building the specification by blocks:

  • setup: Now we need more ingredients. I iterate to create 2500 spanish omelet standard recipes, and I'm afraid there will be just one chef to make them all.
  • when: This time there's only one chef cooking all the omelets sequentially. Later on we'll see how long the process is going to take.
  • then: Final conclusion. How many eggs, potatoes, onions... and much important, how long it takes to make omelets for so many people.

Here you have some outputs from Eclipse Junit runner:

It's funny isn't it?

No comments:

Post a Comment