Back
  1. Introduction to BDD

    October 28, 2010 by nickmulder comments

    What is BDD

    “BDD focuses on obtaining a clear understanding of desired software behaviour through discussion with stakeholders. It extends TDD by writing test cases in a natural language that non-programmers can read. Behavior-driven developers use their native language in combination with the ubiquitous language of domain driven design to describe the purpose and benefit of their code. This allows the developers to focus on why the code should be created, rather than the technical details, and minimizes translation between the technical language in which the code is written and the domain language spoken by the business, users, stakeholders, project management, etc.” Wikipedia

    For history on BDD check out Dan North’s blog post Introducting BDD.

    Rails 3 & BDD

    Lets setup a sandbox app to play with:

    http://gist.github.com/624162

    The -T tells rails to create the project without TestUnit.

    Lets add some gems to the Gemfile:

    http://gist.github.com/624178

    There are probably newer versions of Rails, Rspec-Rails and Remarkable out there, so check out the github repo to make sure you are using the latest versions.

    Now that we have our Gemfile lets install some gems with bundler:

    http://gist.github.com/640560

    Assuming everything went well we can install rspec into our rails project with:

    http://gist.github.com/640562

    This will setup a /spec directory in your project with a spec_helper.rb file which sets up the environment for running specs. It will also create a autotest directory with a discover.rb file which helps the autotest tool decide which files to reload.

    You can test the setup by running the following:

    http://gist.github.com/640580

    Rake spec is the bit we are interested in. Currently we don’t have any specs but at least we know its all running properly.

    I recommend installing a few extra gems to better the BDD experience. Colored is a gem which will get some nice red/green/yellow colours going in your terminal window. Autotest is a great tool that will continually run your specs for you as you edit your code. The autotest/discovery.rb file will make help autotest to rerun the specs for the files you edit in your rails project. You can also install autotest-growl if you have growl installed. After installing the gems you have to add two files to your home directory .autotest and .rspec.

    Here is the command to install the gems, and the contents of the two files you should create in your home directory:

    http://gist.github.com/640587

    Our First Spec

    Lets create our first spec. You can name it what ever you like, but make sure it ends with _spec.rb. Add the file to your spec directory and copy the following into it:

    http://gist.github.com/640599

    This example isn’t very interesting, but it should already run; You can start up ‘autotest’ or run ‘rake spec’ to see the example run. You should see output similar to this:

    http://gist.github.com/640605

    Rspec/BDD has this great concept of ‘Pending’ examples. The idea is when you start out to write a new feature you start by writing all the requirements for the feature as pending examples. Once you get into this workflow the pending examples work as a todo list and helps to keep you on track to implementing that new feature.

    To implement a pending example simply give it a block:

    http://gist.github.com/640616

    This example still isn’t very interesting, but it is at least an example now. Autotest or ‘rake spec’ should now be showing you something like this:

    http://gist.github.com/640617

    You should also have seen some green ‘love’ if you are running autotest with growl.

    RSpec Expectations

    Inside of your examples you simply state expectations. IE. The output of this method call should equal this string, or this array should have n items.

    As it says our second example “should do something”. BDD uses this kind of language to be descriptive as well to help the example to stay on task. Our second example is doing something with the should method. Rspec has two very simple methods that we can call on any object to state our expectations. They are should and should_not.

    Here is a second example for our spec which shows them in action:

    http://gist.github.com/640623

    Our first expectation in this example says “an empty strings class should be String”. Our second expectation says “an empty strings class should not be Integer”. Running this we should get a green (passing) example.

    RSpec Matchers

    These Expectations, should and should_not are useless with out Matchers. The power of RSpec is in its matchers. We have already seen the simplest matcher in the arsenal, ==. The == matcher simple ensures the left side of the expectation is equal to the right side. If it is equal you get a pass, if it is not equal you get a failure. == can be used with either should or should_not. Avoid using != use ‘should_not ==’ instead.

    There are many more Matchers that come with RSpec, and you can always add your own. Here are just some of the simpler Matchers:

    http://gist.github.com/640662

    There is plenty of info on these and all the other standard Matchers in RSpecs Docs. Most of these do exactly what you would expect them to. Lets create a few other examples to take them for a test drive:

    http://gist.github.com/640669

    Running all these examples we should see the following output:

    http://gist.github.com/640680

    Notice we have this nice nested structure. This came from the —pretty option we put in our .rspec file in the home directory. In addition to testing out the Matchers we also used another concept in RSpec. context is a great way to group together related examples.

    If these Matchers are all new this is a great time to play around in this spec and see what some of the other ones do. If things are not working as expected just go back to the docs and try to figure out where things went wrong. If you have questions hop on IRC and drop us a line in the #torontoruby channel.

    This is the first in a series of posts on the topic of BDD. Next up we will be implementing a simple model BDD style.

    This post is a summary of a talk given at TorontoRB on BDD.


  2. blog comments powered by Disqus