[rspec-users] Role of stories vs specs, revisited

Pat Maddox pergesu at gmail.com
Fri Jan 11 16:16:33 EST 2008


A couple months ago I asked how stories and specs might impact each
other. [1]    If you look at Dan North's example of what's in a story
[2], and you imagine using the spec framework to drive the design, you
can probably imagine a significant bit of overlap in the two.  Is that
a bad thing?  I'm not sure.  It has made me a bit uncomfortable
though, and I've kept that question in the back of my mind these past
few months.

(please forgive any mistakes in the code, I just typed it all into this email)

The traditional way of writing specs has been to organize them around
context, or the fixture used.  This leads to specs that look like

describe Stack, "empty" do
  it "should be empty" do
    Stack.new.should be_empty
  end

  it "should blow up when sent pop" do
    lambda { Stack.new.pop }.should raise_error(StackEmptyError)
  end
end

describe Stack, "with one item" do
  before(:each) do
    @stack = Stack.new
    @stack.push :foo
  end

  it "should not be empty" do
    @stack.should_not be_empty
  end

  it "should return the item when sent pop" do
    @stack.pop.should == :foo
  end
end

One of the guys at work showed me a different style of writing specs.
He organizes them mostly around methods.  So his spec would look more
like:

describe Stack do
  describe "#empty?" do
    it "should be true with no items" do
      Stack.new.should be_empty
    end

    it "should be false with one item" do
      s = Stack.new
      s.push :foo
      s.should_not be_empty
    end
  end

  describe "#pop" do
    it "should blow up with no items" do
      lambda { Stack.new.pop }.should raise_error(StackEmptyError)
    end

    it "return the last item added" do
      s = Stack.new
      s.push :foo
      @stack.pop.should == :foo
    end
  end
end

At first I didn't like it so much.  It goes against the way I've used
for so long, which is to organize the specs around fixtures.  Second,
I'm concerned that in using this style, one might focus more on the
behavior of a method, rather than the object as a whole.

I've slowly been coming around to it though.  I think the
method-focused approach has some significant benefits for the
developer.  It serves as excellent documentation.  If I want to use
#pop, I can just look at the spec and see exactly how it's going to
behave.  If I make any modifications, I know exactly where it goes.
Contrast this with the context approach, where I might have to hunt
through a couple example groups to find all the examples that use the
method.  I think writing specs with more focus on methods ends up
being a lot more maintainable in the long run.

My issues with that approach were that it doesn't follow tradition,
and the nebulous "what if I forget how to BDD well?"  The benefits are
far more concrete and practical.  I can use stories to express stuff
at a high level, in terms of the domain, and write these
method-focused examples to really help me out as a developer.  Which
is how the benefits are supposed to be derived in the first place.

Interestingly, if you take a look at Dan's example, you'll see that it
is based around one method.  That sort of throws me for a loop.
However at a high level, it's actually based around one feature that
the customer wants.  The fact that it's all the same #withdraw method
under the hood is mostly coincidental.

I kind of lost steam towards the end here :)  I'd love to know what
you guys think.

Pat


[1] http://rubyforge.org/pipermail/rspec-users/2007-November/004455.html
[2] http://dannorth.net/whats-in-a-story


More information about the rspec-users mailing list