behaviour driven development with beanSpec

first of all, this is no introduction to Behaviour Driven Development, as there are already many great articles and informations available, so the world doesn’t need another entering guide yet.

this post is rather an introduction to beanSpec, a little tool for writing specifications in the sense of BDD in Java. beanSpec tries to provide a clear conceptual model that is easy to capture and apply (if you’ve seen RSpec so far, you will immediately feel familiar with beanSpec, because the conceptual model is almost the same).

beanSpec by example

let’s dive into beanSpec by example – specifying the behaviour of java.util.Stack (ok, that’s not the most fancy example, but it will serve the purpose of an introduction very well. in addition to that, you can compare it to the given @Stack example at RSpec’s home and see the conceptual similarities).

we start the example with a new specification class, as all specifications within beanSpec start by extending beanSpecs class Spec:

public class StackSpec extends Spec {
}

that was easy!
now we want to specify the behaviour of a non empty Stack. therefore we simply have to define a method that will specify that context, so we should name our method according to the particular context (‘a non empty Stack’).

public class StackSpec extends Spec {
  @Specification
  public void a_non_empty_Stack(){
  }
}

i used a rather unusual style for the methods name (it increases the readability of the Spec in my opinion). of course you could use good old camel case style whenever you want to! further on, you may have noticed the annotation @Specification. it’s for marking only those methods within your Spec, which should be evaluated, since you are free to have arbitrary helper methods within your Spec.

context

next we firstly have to describe the context within the method’s body, that is a non empty Stack:

...
@Specification
public void a_non_empty_Stack(){
    final String lastItemAdded = "elem 3";
    Stack aNonEmptyStack = is(
        new DescriptionOf <Stack>(){
            public Stack isDescribedAs(){ 
                Stack<String> stack = new Stack<String>();
                stack.push( "elem 1" );
                stack.push( "elem 2" );
                stack.push( lastItemAdded );
                return stack; } } );
...
}

we’ve pushed three elements onto the Stack. Note, that we’ve defined the last pushed element outside the description, since we will refer to that element in the following statements.

statements

now we are ready to specifiy the behaviour of this context within the method. therefore we declare every expected behaviour in a textual style, followed by one or more operations and statements, that will specify the behaviour programmatically in a checkable way:

...
it( "should not be empty" );
state( aNonEmptyStack ).should( not( be( empty() ) ) );
// or alternatively: state( aNonEmptyStack.empty() ).should( be( true ) );
...

predicates

using predicates for defining the claimed behaviour (that is the expression inside the called should() method) gives you the freedom to combine such predicates in any combinations that makes sense to your specific context. since it’s very easy to write your own predicates, it’s even possible to come up with your own set of domain specific predicates, giving you the chance to build a kind of domain specific vocabulary for your specifications.

for example we could be in need of a predicate that checks the given result of a statement against a regular expression, so that we could state the following:

...
it( "contains only elements that start with 'elem'" );
for( Object elem : aStackWithThreeElements.subList(0, 3) ){
    state( elem ).should( match( "elem.*" ) );
}

of course this special predicate makes no sense in the actual context (and even would fail, since our last pushed element isn’t compliant in regard to the stated pattern), but for demonstrations sake here’s the predicate we would have to come up with:

public class MatchPredicate extends AbstractPredicate {
    private String pattern;
    public MatchPredicate( String pattern ){
        this.pattern = pattern;
    }
    public boolean isValidFor(Object bean) {
        return bean.toString().matches( pattern );
    }
    public static Predicate match( String pattern ){
        return new MatchPredicate( pattern );
    }
}

now that we’ve seen how easy it is to extend beanSpec’s vocabulary with domain specific predicates, let’s have a second look at some of the predefined ones, that you can use out of the box:

...
it( "should return the top item when sent #pop" );
state( aNonEmptyStack.pop() ).should( be( lastItemAdded ) );
it( "should return the top item when sent #peek" );
state( aNonEmptyStack.peek() ).should( be( lastItemAdded ) );
it( "should NOT remove the top item when sent #peek" );
aNonEmptyStack.peek();
state( aNonEmptyStack.peek() ).should( be( lastItemAdded ) );
it( "should remove the top item when sent #pop" );
state( aNonEmptyStack.pop() ).should( be( lastItemAdded ) );
while( ! aNonEmptyStack.isEmpty() ){
    state( aNonEmptyStack.pop() ).should( not( be( lastItemAdded ) ) );
} ...

you may have asked yourself why you are able to call the method pop() in the first statement, and then stating in the next one, that the top level element is even the lastItemAdded (but pop() should have removed that element in the previous statement, right?).

this is one of the mechanics of beanSpec: every single specification statement (starting with it() ) gets a fresh new Stack object according to the definition at the start of the method. you then can operate on that object within your operations and state() expressions and change it’s state if necessary. as soon as you start with a new specification statement (initiated by the next it() call) you’ll again operate on a new instance.

specification templates

let’s assume we want to specify the behaviour of Stack in another context (i.e. empty Stack, full Stack, Stack with one element left to full, …).
it’s very likely that you have to repeat some of your statements. according to the DRY principle, beanSpec gives you the chance to define one ore more so called specification template methods, that can be refered in your concrete context specifications:

...
// specification template
public void a_non_empty_Stack( Stack aNonEmptyStack, String lastItemAdded ){
    it( "should not be empty" );
    state( aNonEmptyStack ).should( not( be( empty() ) ) );
    ...
}
// another specification template
public void a_non_full_Stack( Stack<Object> aNonFullStack ){     it( "should add to the top when sent #push" );
    Object newlyPushedElement = aNonFullStack.push( "new Element" );
    state( aNonFullStack.peek() ).should( be( newlyPushedElement ) );
}
@Specification
public void a_stack_with_3_elements(){
    final String lastItemAdded = "elem 3";
    Stack aStackWithThreeElements = is(
        new DescriptionOf <Stack>(){
            public Stack isDescribedAs(){
                Stack<String> stack = new Stack<String>();
                stack.push( "elem 1" );
                stack.push( "elem 2" );
                stack.push( lastItemAdded );
                return stack; } } );
    itShouldBehaveLike( "a_non_empty_Stack", sharing( lastItemAdded ) );
    itShouldBehaveLike( "a_non_full_Stack" );
    // additional Statements
    it( "should be of size 3" );
    state( aStackWithThreeElements ).should( have( size( 3 ) ) );
    ...
}

as you can see, there are two specification templates. a specification template takes at least one argument – the object that must stand the stated specifications within the template. should there be other information that should be shared, they will follow as additional arguments.
now you can refer to those specification templates by stating itShouldBehaveLike, followed by the name of the template.
note, that the ‘object to specify’ is implicitly populated by beanSpec itself. all additional arguments that should be shared with the template have to be populated via an explicit sharing() statement.

specification verification summary

having specified the behaviour (and implemented Stack), we can check if Stack behaves as expected by running the StackSpec (at the moment there’s only a ConsoleRunner).
beanSpec gives a summary of the evaluated specification, making it easy to read the whole specification in a textual form and recognize any misbehaviour, should one of the stated specifications should fail.

STACKSPEC
—————

a_stack_with_3_elements
– should not be empty : ok
– should return the top item when sent #pop : ok
– should return the top item when sent #peek : ok
– should NOT remove the top item when sent #peek : ok
– should remove the top item when sent #pop : ok
– should remove the top item when sent #pop : ok
– should remove the top item when sent #pop : ok
– should add to the top when sent #push : ok
– should be of size 3 : ok
– contains only elements that start with ‘elem’ : failed

statements : 10, ok : 9, failure : 1

an_empty_Stack
– should add to the top when sent #push : ok
– should complain when sent #peek : ok
– should complain when sent #pop : ok

statements : 3, ok : 3, failure : 0

Specs : 2, total statements : 13, ok : 12, failure : 1

that’s it so far – a short introduction to beanSpec.
i would love to hear some feedback from you, should it be criticism or feature requests – any feedback is appreciated!

Advertisements
Posted in bdd. 4 Comments »

4 Responses to “behaviour driven development with beanSpec”

  1. Dr.G. Says:

    It would be great with a side-by-side comparison of the code you would type in junit4.4. Your above example has not convinced me that what you are doing is mere syntactic sugar of the existing tools without much benefit.

    Why beanSpec over Junit? That’s one of the motivational points missingvvv

    -Dr. G.

  2. Mario Gleichmann Says:

    Dr.G.,

    first of all thanks for your feedback!

    I think the question shouldn’t be ‘why beanSpec over JUnit’ rather than ‘why or when BDD over TDD’.
    Since both are only tools that serve a specific task, their value don’t lie in themself inherently but in the goals they try to achieve, resp. try to support.
    It’s rather diffcult to summarize the advantages of BDD by words, since they remain abstract. For myself, it ‘clicked’ when i get used to BDD on a daily work basis. You’ll come to the point that it’s rather about specifiying the behaviour of a component than to test some methods in order to proof that you’ve implemented the code right (didn’t i say words remain abstract?).
    Of course you can do ‘BDD’ with JUnit, but it’s concepts and language (TESTSuite, TESTCase, @Test, …) points to a different direction, so you’ll most of the time leave the right path of specifying behavior but lose yourself in testing methods with a more or less loose connection to the behavior you’ll want to specify in effect. According to the Saphir-Worf hypothesis, BDD tries to guide your concentration back to the specification of behaviour, supporting this goal by providing an appropriate language (component SHOULD behave like stated).
    Coming back to the starting question, beanSpec is only a little tool, providing such a language to make it more easy to describe the behaviour of a component and stay focussed on that.
    That said and having the before mentioned statement (‘words remain abstract’) in mind, I would suggest you may start reading some of the articles I’ve mentioned in the post and start practicing BDD by yourself. It’s the best way to get that ‘click’.

    Greetings

    Mario

  3. arpit Says:

    Is there any documentation available?

  4. Adina Zaituna Says:

    What a magnificent blog. I use up hours on the internet evaluation blogs, regarding tons of distinct subjects. I like first award kudos to whoever created your website and secondly to you for writing what i can just illustrate as an fantasticpost. I honestly think there is a expertise to writing articles that only a hardly any posses and frankly you boast it. The combination of informative and quality content is definitely exceptionally rare with the great sum of blogs on the internet.


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: