InfoQ catching up with the easyb team

Posted by Ken Brooks Tue, 23 Sep 2008 04:23:00 GMT

Craig Wickesser from InfoQ pinged the members of the easyb dev team recently in preparation for an article about BDD and bringing it to the masses.

The focus of the article is on easyb. It references Rod’s excellent JavaWorld article and then goes on to dive into a brief Q&A with the easyb team.

If you want some inside information on where easyb is headed, then Behavior-Driven Development for Everyone by Craig is hot off the presses today and is a must read.

Posted in  | Tags ,  | no comments

pretty print your behavior

Posted by Ken Brooks Sun, 21 Sep 2008 00:00:00 GMT

Our favorite BDD tool is about to get some upgrades that give you that warm fuzzy feeling inside. Just like waking up on a cold winter day to the wonderful smell of baking cookies. Yummy!

Html reports you say? Well hello Mr. Fancy Pants!

All the goodness you’ve come to love about the existing easyb reports have now come to life in living color. In order to enable them, you’ll just need to configure another report in exactly the same way as other reports.

via ant in your easyb task:

<report location="target/easyb-report.html" format="html" />

or on the command line:

c:>java org.disco.easyb.BehaviorRunner my/path/to/MyStory.groovy -html ./target/easyb_report.html

Currently available are a Summary, Specification List, Stories List, Specification List Plain, Stories List Plain.

The Summary you saw just above. It will show you an overall summary, and summaries at the specification and story level. Any failed behavior count will be highlighted in red and pending behaviors will be highlighted in a wonderfully peaceful reminder color of purple.

The Stories List provides all of that that but takes it a couple of steps further. All of the elements of the stories (any scenarios, givens, whens, thens, etc.. ) will show up when the story name is clicked on and for any failures you’ll get an eyeful of failure messages along with part of the relevent stacktrace.

More of the same for Specifications list.

Since all we had prior to easyb 1.0 was a text only format, we got sentimental and included a stripped down, nearly text only, format here as well. Ok, so we didn’t really get sentimental, we actually thought this is really where the rubber meets the road when it comes to bringing stakeholders and developers together. As part of your build you can now publish these reports and share them with those interested parties. Makes BehaviorDrivenDevelopment truly, uh, easy!

All of this and more is waiting for you in easyb 1.0. Just like those tasty warm cookies, its still in the oven and I’ll bet you can’t wait to get your hands on it.

Keep an eye on the following sites for more announcements about the availability of 1.0.

Posted in  | Tags , , , ,  | 1 comment

Executable Documentation - EasyB style

Posted by Ken Brooks Mon, 04 Feb 2008 21:45:00 GMT

One of the challenges of maintaining and enhancing an existing system is that the documentation goes out of date probably before you even finish it the first time. Whenever someone has a question for me about how does something work I usually refer to the location of truth. That would be the code itself, which is always the most up to date source of documentation. So the closer to the source you get the better chance your documentation has of standing the test of time.

Unit Tests helps in this area in that they can outline the assertions we are placing on our code. That too must stay up to date because it is also close to the code. Unfortunately unit tests are often more complex than the code they are testing and ultimately end up not being very good sources of documentation either.

There has to be a way to build human (possibly even business person) consumable documentation that stays in sync with the truth.

Enter EasyB.

EasyB is a BDD testing framework written in groovy and java. It provides what we like to call executable documentation. This is achieved by taking TDD, all sopping wet with techy mess, and throwing it in the evolutionary dryer with a nice fabric softener. Out from the other end pops a nice fluffy testing framework that can not only provide up-to date documentation about the application every time it is built, but can even bridge the gap between business requirements and developer interpretation.

It has two supported ways to write specifications. Behaviors and Stories. Its just a matter of personal taste on which you use for each component in your project. Behaviors often are shorter and good for utilities. Stories are more verbose and usually map to a series of interactions.

Behaviors look like this:

it "should return null for null input to trim", {
  ensure(StringUtilPartial.trim(null)) {
    isNull
  }
}

it "should return the string without whitespace at either the end", {
  StringUtilPartial.trim(" somestring ").shouldNotBe null
  StringUtilPartial.trim(" somestring ").shouldBe "somestring"
}

Stories look like this:

scenario "appending string to empty string buffer", {
  given "an empty string buffer", {
    stringBuffer = new StringBuffer()
  }

  when "a string is appended", {
    stringBuffer.append("somestring")
  }

  then "the buffer should contain the string appended", {
    stringBuffer.toString().shouldBe "somestring"
  }
}

scenario "appending string to existing string buffer with existing data", {
  given "a string buffer with an initial value", {
    stringBuffer = new StringBuffer("abcd")
    originalStringBufferValue = stringBuffer.toString()
  }

  when "a string is appended", {
    stringBuffer.append("somestring")
  }

  then "the buffer should contain the original value plus the appended value", {
    stringBuffer.toString().shouldBe(originalStringBufferValue + "somestring")
  }
}

What you have just witnessed is that we have tested our code and written documentation at the same time. That documentation will evolve right along with the code its testing and nobody has to be the low man on the totem pole and write documentation.

All well and good, but what we wrote above still wouldn’t be what a business person would consider documentation. Too much techy goobledeegook in there. Easyb has another trick up its sleeve especially when dealing with the story based specifications. When I ran the story above a report is generated and here is what the contents look like:

  Story: string buffer
    scenario appending string to empty string buffer
      given an empty string buffer
      when a string is appended
      then the buffer should contain the string appended
    scenario appending string to existing string buffer with existing data
      given a string buffer with an initial value
      when a string is appended
      then the buffer should contain the original value plus the appended value

What?! Where did that english documentation come from? Shhh.. don’t tell your developers that they wrote it.

Check out easyb at easyb.org and join the group to keep up on the latest developments. The current release of easyb is 0.6 and some of the syntax presented above (shouldBe for example) is in the trunk and not a release yet.

Posted in  | Tags , ,

RSpec 1.0 tutorial - before and after

Posted by Ken Brooks Thu, 24 May 2007 22:49:00 GMT

Tonight we’ll be starting down the road of those refactorings I promised and along the way we’ll introduce before and after.

First lets change that snowball itself to be a little more rubyish. In this case that means we will use symbols for the color.

class Snowball
    def initialize
        @color = :WHITE
    end

    def color?(color)
        @color == color
    end
end

Now we can modify the spec to do the same, passing in symbols for the color param.

require 'snowball'

describe Snowball do

    before(:each) do
        @snowball = Snowball.new
    end

    it 'Should NOT be yellow' do
        @snowball.should_not be_color(:YELLOW)
    end

    it 'Should be white' do
        @snowball.should be_color(:WHITE)
    end

    after(:each) do
        @snowball = nil
    end
end

You may have noticed that I did a little more than change the params to use symbols. There are now calls to before and after. If you are from an xUnit background you can think of these as setup and teardown. The before method runs prior to each example. before(:each) is the same as before because :each is the default param. The after method runs post each example. The same default of :each applies to after so after(:each) is identical.

Updated 2007-05-25

Aslak (Core developer of RSpec) was kind enough to point out something that I should have clarified:

Each example (instance) runs in a new instance anyway, and the instance variables are garbage collected. The after(:each) here has no effect, and since it has no effect, doing it is confusing.

So in my example above the after method is not doing anything of value. That @snowball will be garbage collected without having to set it to nil. I just needed something to plop in there to show that I could be doing something.

End Update

There are also before(:all) and after(:all) that can be used. These are mostly discouraged as it may cause side-effects by having dependencies between examples. I came across a scenario at work (in Java-land) where this actually applies. I was using JUnit to write a func test that can be used as a test client of a deployed J2EE service. Before any calls can be made to the service we must initialize (authenticate). Once that initialization is done then we can call our service as many times from anywhere in our code using a static service wrapper. So in my test since there is only one setup method I was forced to write code similar to this:

    private static boolean initialized;

    public void setUp() {

        if(!initialized) {
            SubSystem.init();
            initialized = true;
        }

        doSomeOtherSetupTask();
    }

That saves the overhead of authenticating before each test. Unfortunately its ugly to me.

In rspec (altho I’m not sure I would use it to drive a client test like I did with JUnit) I suppose that code would look like this:

    before(:all) do
        sub_system.init
    end

    before(:each) do
        do_some_other_setup_task
    end

Now that is tasty goodness.

Tags ,  | 2 comments

RSpec 1.0 and tutorial - Basics

Posted by Ken Brooks Mon, 21 May 2007 00:30:00 GMT

RSpec has reached 1.0.0 (congrats to that team).

What is RSpec you ask? Straight from their site:

RSpec provides a Domain Specific Language with which you can express executable examples of the expected behaviour of a system.

A little better (and foreshadowing) explanation from their site:

…use RSpec to #describe Behaviour of a system using Examples of how #it should work.

Over the next few posts I’ll be going thru some of the features with small tutorials.

First up, the basics of installing RSpec and writing your first working spec. We’ll be going thru the specs of a snowball, now that summer is here and I spent the day sweating my snowballs off.

Get rspec

sudo gem install rspec

Create your first spec by creating snowball_spec.rb and adding the following to it.

describe Snowball do
end

That is telling us that we are going to describe the behavior and requirements for a successful implementation of a snowball.

Now is as good a time as any to fire up rspec and see what the magic is all about.

spec snowball_spec.rb

That just produced a ./snowball_spec.rb:1: uninitialized constant Snowball (NameError) message. Not exactly shaping up to be the greatest tool in the world is it? Take a closer look. Its actually telling you where to go next. Yep, create a Snowball class.

class Snowball
end

Don’t bother running spec again as you’ll be presented with the same error again. You need to tell the spec we depend on that snowball class. Modify your snowball_spec.rb to require the snowball.

require 'snowball'

describe Snowball do
end

Now if you run spec again you should see a little more positive results.

$ spec snowball_spec.rb 


Finished in 7.0e-06 seconds

0 examples, 0 failures

That basically tells us that we are ready to really start describing the behavior of our snowball.

Lets add an example to our spec. We are going to make the statement that snowballs should not be yellow (unless you really don’t like the kid down the street).

require 'snowball'

describe Snowball do
    it 'Should NOT be yellow' do
        snowball = Snowball.new
        snowball.should_not be_color("yellow")
    end
end

That is pretty easy to read, and if you now run spec with the --format specdoc it finally hits you why RSpec is different and has its niche as compared to xUnit tests. We really are documenting the behaviour of a system and writing code to meet that required behavior. Now you can have your Keanu Reeves (Neo) ‘Whoah’ moment.

Ok, enough of that moment, lets finish up the snowball code to make this spec run again. And I’ll get back to creating that snowball instance in the middle of the test. If I don’t then please ping me and remind me.

class Snowball
    def color?(color)
        color == "white"
    end
end
$ spec snowball_spec.rb --format specdoc

Snowball
- Should NOT be yellow

Finished in 0.006263 seconds

1 example, 0 failures

Without changing the Snowball class, we should now try and see if the positive test works also.

require 'snowball'

describe Snowball do
    it 'Should NOT be yellow' do
        snowball = Snowball.new
        snowball.should_not be_color("yellow")
    end

    it 'Should be white' do
        snowball = Snowball.new
        snowball.should be_color("white")
    end
end

Obviously (for the more experienced users) there are a few things that will need to be refactored out but in the interest of simplicity I left them that way to start.

That covers the basics of using RSpec. We described the behavior of an object and then created some examples of its behavior.

Next section we’ll dig a little deeper and start doing those refactorings.

Tags , ,  | no comments