Behavior Driven Development: Inside-Out vs Outside-In Pattern 3

Posted by Kurt Schrader Fri, 04 May 2007 07:32:00 GMT

Recently at work we've been having a bit of an argument over the proper way to structure a spec while doing Behavior Driven Development.

I'm going to illustrate a couple of patterns that have emerged using the simple example of a sword that should tell you if it is sharp or not, depending on whether it is new or used.

One camp at my current job, likes to use what I'm calling the Inside-Out Pattern for writing specs. This group likes to start with the method name and then define behavior for it. An example of this is shown here (in RSpec syntax):

describe "sharp?" do 
  it "should tell you if it is sharp or not" do
    Sword.new(:status => 'new').sharp?.should == true
    Sword.new(:status => 'used').sharp?.should == false
  end
end  

Their argument for this pattern is that all of the code for that method stays in one place, so it's easy to see if you've covered everything in that method.

The argument against this is that your specs are harder to understand and you can't really do real TDD with this method of development.

The other camp likes to use what I'm calling the Outside-In Pattern. This pattern describes the possible states of the object first, and then describes what the object should do in each state:

describe "A new sword" do
  before(:each) do
    @sword = Sword.new(:status => 'new')
  end

  it "should tell us that it is sharp" do
    @sword.sharp?.should == true
  end
end

describe "A used sword" do
  before(:each) do
    @sword = Sword.new(:status => 'used')
  end

  it "should tell us that it is not sharp" do
    @sword.sharp?.should == false
  end
end

The argument for this pattern is that it is more descriptive of what the object should do and it helps with TDD.

The argument this is that you get too many descriptions in your spec, and they can get hard to read. Also, the behavior for a single method in a class is spread around the multiple descriptions, so it becomes harder to make sure that all of the behavior of your method is covered.

Most of the specs that we've written so far seem to skew towards one or the other of these options, but there's no consensus on which of them is better yet, so I figured I'd throw it out there and see if anyone has experience one way or the other and which one has worked better.

Please let me know in the comments.

(And yes, before anyone asks, I'm firmly in one of the camps, and yes, I purposely didn't reveal which one here. I'll be talking more about it in a later post.)

Update: My coworker Dustin points out another way of doing specs that rests firmly in the middle of these two views.

Trackbacks

Use the following link to trackback from your own site:
http://kurt.karmalab.org/trackbacks?article_id=behavior-driven-development-inside-out-vs-outside-in-patterns&day=04&month=05&year=2007

  1. The vanilla example used in most blog posts for BDD is some incarnation of de novo domain object specification, that is, specifying the behavior of a simple domain object from scratch. David Chelimsky’s stack example is a decent online examp...
Comments

Leave a comment

  1. Avatar
    Kerry Buckley about 3 hours later:

    I definitely prefer outside-in. A couple of justifications:

    1. The context should represent a state, not an object or method. "A sword" is only a context if you're specifying behaviour for all swords, "A new sword" describes a sword in a certain state, and "sharp?" seems to me to be a programmer-centric way of writing specs (more like an early xUnit approach, where we used to generally write one test per method).

    2. I also like to keep to one assertion per test, so the inside-out example would have to be split into "should return true when the sword is new" and "should return false when the sword is used". This is slightly more expressive than your example, but still seems to describe what the code does, rather than how the object behaves. This might not always be a bad thing, but I don't think it's really BDD.

  2. Avatar
    Aslak Hellesøy about 4 hours later:

    Outside in man. Inside out sounds like after-the-fact testing, missing the point of TDD/BDD.

    You can say:

    sword.should be_sharp

  3. Avatar
    Moses Hohman 2 days later:

    One of Kurt's mysterious coworkers here. Another problem with the inside-out approach above is the name of the example, "sharp?", which is pretty meaningless when you see it in the HTML output of a bunch of specs. Funny for me to say that, because I was the guy discussing this with Kurt. I'm not sure if I'm in a camp, but if I am, I wouldn't describe the camps in this way.

    I tried to write something about the original example that prompted this discussion, but midpost realized that the method in question (blank?) was only used in one place, in the spec code for a collaborating class, so I thought that was a bad example. So instead I focused on a similar situation in the specification of the behavior of the same class. Hopefully more detail helps clarify things.

Comments