BDD: Forces and the “given X, when Y, then Z” pattern

Thinking more about the issue mentioned in my previous post, I’ve come up with a possible set of forces that push you in one direction or another, that is toward organizing your specifications around method behavior vs. organizing around object state behavior or vice versa):

  1. Clearly, if you’re specifying procedural code (Rails helpers, many class-level methods), there’s no state, and you should organize your specifications around methods.
  2. If your object has more attributes/more states and fewer methods/less business logic, then it’s probably clearer to organize your specifications around the behavior of the methods. If, however, the object has fewer attributes and more methods/business logic, then it is clearer to organize around the various object states, each with a number of specifications of the behavior of each method in that state. This is probably somewhat debatable, but it might be true. Perhaps there’s a better characterization of this force. Definitely less code if you follow this approach, and less code (expressing the same meaning) is usually clearer. It also seems to me that fewer contexts are usually easier to understand, because there is less information to parse.
  3. If your objects have states that are expensive to set up (i.e. lots of mock expectations), then it’s better to organize specifications around those states. However, this might also be a code smell that your classes should be more loosely coupled.

Another way to think about this is in terms of how each spec reads. Dan North in his Introducing BDD article talks about formulating specifications using the language pattern: “Given X, when Y, then Z”, so for example, “Given an assay criterion with nothing specified, when asked for its corresponding SQL conditions, it should return nil.” There are several ways you could express this in RSpec (leaving out the before block and the body of the spec). Organized around the object state, it would be:

describe "Given an assay criterion with nothing specified" do
      it "should return nil when asked for its corresponding SQL conditions (:to_conditions)" do
        ...
      end
    end

or, organized around the method:

describe "When an AssayCriterion is asked for the corresponding SQL conditions (:to_conditions)" do
      it "should return nil if nothing was specified" do
        ...
      end
    end

or Dustin’s hybrid approach:

describe "Given an assay criterion with nothing specified, when asked for the corresponding SQL conditions (:to_conditions)" do
      it "should return nil" do
        ...
      end
    end

I’m not sure that tells you which one is better, but there it is.

Also, I found a couple more good links about BDD. I’ll list them and other useful stuff on general BDD I’ve found here, please let me know about any others:

Leave a Reply