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.
PLEASE DON'T KILL THE MESSENGER!!!
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'
spanishOmelet.with{
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.
- 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.
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()
2500.times{
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