GSpec for Java BDD


What is BDD? Webster defines it as Behaviour Driven Development. (Not that Webster, this Webster! Yeah, I asked him the other day and he was all like, “Behaviour Driven” in his tiny voice.) I stumbled across the idea a while ago thanks to the lovely folks over in the Ruby camp. They have taken the idea of Test Driven Development (know as T.D.D. for those of you who have A.D.D.) to the next level giving us a tool called RSpec. While the tool is fascinating the idea behind it is even more intriguing. (By the way, I’m not giving or taking all credit to/from the Ruby camp because I’m not sure who fathered the idea. I mention them because they were the first ones that introduced me to the concept. But as concepts go everyone want their name mentioned so I’ll just pretend for the sake of discussion that I made the entire idea up all by myself with no help or insight from Ruby or anyone else whatsoever!) BDD focuses on the ideas central in Neuro-linguistic programming (NLP). If you read from that link you be pummeled with long-head words like axioms and adherents as well as a bunch of theory on psychology. The idea is simple. The words we choose affect how people think about things. That’s essential because the way we think about things effects how we do things. How we do things effects things that are done to us. Things that are done to use effects… well I’m off topic and I’ve probably oversimplified and confused everybody. Let’s try an example of the idea.

If your spouse told you to, “take the garbage out front!” You would likely receive that as a direct order or a challenge. Some people may take it as a threat. “Take the garbage out or else what?”, is the thinking. However, if your spouse informed you that, “the garbage needs to go out for trash night” you would likely be more receptive. Another example would be “Move from in front of the T.V.!” once again words that are likely to be perceived as threatening. However, “I’ll take the garbage out as soon as I can see who’s winning the game.” could result in a much more complimentary reaction from a spouse. (Not in all cases and I should tread lightly because in in dangerous and uncharted territory with our discussion here.)

What does trash and Football have to do with programming?
Most football fans talk trash when they write code. (Does that tie it together well enough?) The truth is that code is made up of words. A popular observation is that code is primarily used for/by people, a fact that is easily forgotten in the industry. When you use the right words you convey your intentions clearly which allows people to understand and respond accordingly. That leads to increased productivity resulting in happier times for all involved. When you choose the wrong words your intentions are lost which result in people following the wrong direction and creating their own paths. You code should convey intention clearly focusing heavily on the what and why of a process rather than the how. Those intentions should match the intentions of the user of that code. The intentions refer to the desired behavior. The net affect is that choosing the right words to describe the intentions results in proper behavior (you desire your spouse to behave by moving out of the view of the TV, choose your words correctly). In short, you achieve the intended behavior best by choosing the right words. Because humans do not respond well to direct instruction (think how you might not respond to, “take the garbage out front”) it makes the most sense to write programming logic in a way that it reads less like instruction and more like a story. Starting from TDD you understand that the test is written first. Since the test is also programming code it too should read like a well written description of intended behavior. That is the big idea behind BDD.

Fluent Interfaces
One of those high octane words describing pretty programming logic, fluent interfaces is a term coined by Martin Fowler. It is a means of making your source code easy to ingest, heavy on intention and low on calories. I take advice from him and others such as Kathy Sierra who taught us the importance of coding like a girl. I’ve taken a stab at writing fluent interfaces in the past and later learned that practicality sometimes becomes more important than pretty design. However, fluent interfaces, girlie coding habits, and just plain self documenting method signatures add way more value than they remove. Adopting these practices when writing tests will make those tests read more like specifications of intended behavior. GSpec is born as a test framework that operates as a specification framework which blesses your code with such fluent interfaces at runtime. I don’t even like using the word tests because it is the wrong word to describe what we actually should be doing when we follow TDD or BDD. I prefer the word “specification” and would rather refer to the process as Specification Driven Development or SDD. (Only that sound too much like STD which could distract from the overall benefits of the practice.) Remember, in theory, choosing the right words more likely results in the intended behavior.

Enough theory, lets get to some examples
Programming is all about making dough right? So let’s make some bread! I’ll walk through a fictitious example of making toast TDD style then we’ll see what BDD adds to the design. Let’s pretend we want to make toast with TDD. Yes, most people use a standard toaster for this purpose but it isn’t as much fun as writing our own bread from scratch isn’t it? We start with an empty test and an interface which doesn’t exist yet. (TDD when done properly uses your imagination to pretend your interfaces exist.):

public class BreadTest extends TestCase {
    Bread bread;
}

Then we add our tests. I’m thinking that we would set the temperature of our bread to 325 degrees before it turns into toast, though I have no idea if that’s actually right in the real world. (My wife is the true cook of the family.)

public class BreadTest extends TestCase {
    Bread bread;

    public void testHeatCooksBread() throws Exception {
        bread.setTemperature(325);
        assertEquals("golden brown", bread.getColor().toLowerCase());
        assertEquals("crisp", bread.getTexture().toLowerCase());
    }
}

That gives us our interface that my IDE (that’s an Integrated Development Environment or a tool to write computer programs for my not so tech readers who are bold enough to try to understand what I do after work.) happily generates for me here:

public interface Bread {
    void setTemperature(int degreesFarenheit);

    String getColor();

    String getTexture();
}

Making our test complete, we add an override to the setup method so we can create a slice of wheat bread.

    protected void setUp() throws Exception {
        bread = new WheatSlice();
    }

I use my IDE to stub out the implementation of our bread (you can type the code yourself if you’re hard-core enough).

public class WheatSlice implements Bread {
    public void setTemperature(int degreesFarenheit) {
    }

    public String getColor() {
        return null;
    }

    public String getTexture() {
        return null;
    }
}

Compiling and running everything gives us the red bar that we’ve grown so used to from TDD. Now making it pass is fairly simple.

    public void setTemperature(int degreesFarenheit) {
        this.degreesFarenheit = degreesFarenheit;
    }

    public String getColor() {
        return (degreesFarenheit >= 325 ? "golden brown" : "light brown");
    }

    public String getTexture() {
        return (degreesFarenheit >= 325 ? "crisp" : "soft");
    }

Not bad for a slice of wheat but we weren’t as concerned with behaviour as we could have been. To show you what I mean let’s consider making toast with GSpec BDD style. (Editorial note: GSpec can also be used for other random household tasks such as thinning paint, polishing tile, or greasing the pan prior to baking.) I leap into action with the following spec:

package com.craig.sandbox

def the = new com.craig.gspec.GSpecBuilderRunner()
the.context('A slice of bread') {
    initially() {
     the.bread = new WheatSlice()
    }

    specify('Adding enough heat to a slice should turn it golden brown and crispy.') {
        the.bread.addHeat(100)
        the.bread.should_not_be_cooked
        //Why not? Because it's not hot enough!

        //Let's add more heat...
        the.bread.addHeat(100)
        the.bread.should_not_be_cooked
        //Why not? Because it's still not hot enough!

        //Let's add more heat...
        the.bread.addHeat(125)
        //Now we should be cooking with gas... err.. Groovy ...err GSpec!
        the.bread.should_be_cooked
    }
}

Without cheating I go to the beginning. I start from an empty Bread interface and an Empty Class definition of our WheatSlice. Running against it gives me the following failure:

A slice of bread
Adding enough heat to a slice should turn it golden brown and crispy.
Caught: groovy.lang.MissingMethodException: No signature of method: com.craig.sandbox.WheatSlice.addHeat() is applicable for argument types: (java.lang.Integer) values: {100}

Now I’m like, “Hey GSpec just pointed out a design flaw! I should blog about it!” Actually, to GSpec’s discredit, it didn’t do anything but complain about a missing method. (It’s far too alpha to suggest good practices. I’ll be adding such advanced AI in my 2.0 beta release.) Best practice lead us to the conclusion that we needed bread bread to allow us to add heat. The difference is subtle but important. Using more English like grammar made me feel as if I should be adding heat instead of setting a member variable as I did before. You see, when writing a TestCase it is easy to focus on testing because you’re writing a test. Also because many/most of your methods begin with the word “test” by convention. When the word test is used repeatedly it becomes natural to think of implementation rather than behaviour. Enough babbling, let’s get onto the rest of our design. I now start filling in the blanks of my design with implementation. (Notice how adding logic is referred to as filling in the blanks of the design.)

package com.craig.sandbox;

/**
 * Created by cliff
 * Date: Apr 6, 2007
 * Time: 11:09:32 PM
 */
public interface Bread {

    void addHeat(int degreesFarenheit);
}

public class WheatSlice implements Bread {

    public void addHeat(int degreesFarenheit) {
    }
}

Now after running I get this:
A slice of bread
Adding enough heat to a slice should turn it golden brown and crispy.
Caught: groovy.lang.MissingPropertyException: No such property: cooked for class: com.craig.sandbox.WheatSlice

Now I start understanding what a slice of bread is supposed to do for me. It’s supposed to allow me to add heat and show me whether it’s cooked or not. I’m focused more on behaviour of adding heat and cooking a slice than I am with setting and examining individual properties. (I understand this is a really contrived example and the design can be argued but bear with me. I’m pretending to know what I’m talking about for the sake of explaining GSpec.) I add [ boolean isCooked(); ] to my Bread interface and generate the following in my WheatSlice class to get to the next step:

    public boolean isCooked() {
        return false;
    }

Now running give me the following:
A slice of bread
Adding enough heat to a slice should turn it golden brown and crispy.
Caught: java.lang.AssertionError: Should be cooked. Expression: (true == prop). Values: prop = false

We ask the simple question, Why is our Bread not cooking? The answer is simple. We haven’t done anything with the heat that we’ve been adding. I’ll combine a few iterations to save space on the page and jump into the final code that satisfies the Spec.

public class WheatSlice implements Bread {
    private int degreesFarenheit;

    public void addHeat(int degreesFarenheit) {
        this.degreesFarenheit += degreesFarenheit;
    }

    public boolean isCooked() {
        return degreesFarenheit >= 325;
    }
}

Running the above through GSpec gives me:
A slice of bread
Adding enough heat to a slice should turn it golden brown and crispy.

Process finished with exit code 0

Before I get hate mail from every TDD advocate complaining about how I did away with the green bar let me explain. JUnit support is still flaky and incomplete. I’ve been also struggling with Maven2 support on the build as I eventually plan to get the entire thing roped into surefire somehow. (I may have to write my own Groovy M2 plugin using Jason’s framework which would be fun.) Greenbars and JUnit aside, it’s the concept that’s really important. What we now have is a slice of bread we can put into a toaster and it should behave accordingly. (Maybe we can design a toaster in a future post.) In conclusion, Behaviour Driven Development (BDD) is what Test Driven Development is supposed to be all about. Whether you use GSpec (which is still very Alpha) or JUnit or TestNG or something else, your design should elevate the importance of how each object or component is used. Implementation should be a matter of filling in the blanks of a well thought out interface with minor bits of functionality. That’s that good stuff there! Ya’ with me? If ya’ feelin’ the same, fill in your name, drop me a comment y’all know the game…

GSpec is a registered trademark of Craig Conglomerates. Any unauthorized use of the name is subject to heavy financial penalties in excess of $250 million. Unauthorized users will also be subject to 495,672,395 repeat airings of alternating back to back episodes of both Mama’s Family and The Golden Girls. A fair use license may be granted upon submitting your name SSN and bank account info to Emporer Craig and subsequently applying for entry into the Hall Of Aim. All other restrictions apply, tax title and tags due on inception. Contact your local dealer for details.

8 Comments

  1. Nice Cliff. It’s good to get a look at what GSpec is looking like. I don’t think this post is necessarily the best intro to GSpec however – you make too many distinct points. I’d like a distilled version. Something along the lines of “you know JUnit, you know rSpec, this is how to get going with Gspec [using Maven]“.

  2. Very nice description and example of BDD. One of the best I have seen in terms of why the language we use is important and how it shapes things. btw – Gspec is great.

  3. Are we able to get our hands on this lovely peace of work?

  4. Куплю Windows Куплю Office -2003/XP enzosoft@mail.ru
    и другое ЛИЦЕНЗИОННОЕ ПО Microsoft
    пишите на е-мейл enzosoft@mail.ru

  5. Launa

    Every weekend i used to visit this site, for the reason that i want
    enjoyment, since this this web page conations
    truly fastidious funny material too.

  6. Wow, this piece of ωriting is good, my younger
    sister is analyzing these kinds of things,thus I am going to let know her.

Trackbacks

  1. JEDI » Blog Archive » links for 2007-04-17
  2. jamesladdcode.com » Blog Archive » Groovy Quick Start Project and gspec BDD …

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

Follow

Get every new post delivered to your Inbox.

Join 251 other followers

%d bloggers like this: