Role of stories vs specs, revisited

A couple months ago I asked how stories and specs might impact each
other. [1] If you look at Dan N.'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 :slight_smile: I’d love to know what
you guys think.

Pat

[1] http://rubyforge.org/pipermail/rspec-users/2007-November/004455.html
[2] What's in a Story? - Dan North & Associates Ltd

On Jan 11, 2008 3:16 PM, Pat M. [email protected] wrote:

The traditional way of writing specs has been to organize them around
end

describe “#empty?” do

end
#pop, I can just look at the spec and see exactly how it’s going to
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 :slight_smile: I’d love to know what
you guys think.

Personally, I think whatever works for you is fine as long as a) it’s
focused on behaviour in the exampes and b) … well … it works for
you!

As for the overlap between stories/specs - you need to understand what
Acceptance Test Driven Development and ATDPlanning are all about to
appreciate that there will, and should be overlap. The two tools
serve completely different purposes. At least that’s their target. If
you use them differently, you won’t lose your license :slight_smile:

But the target of stories are system level descriptions of behaviour.
This will inevitably appear to have some overlap with the specs for
the outermost layers of the system. But when you start refactoring,
those object specifications are going to change - the system specs
(stories) should NOT. At least not as a result of refactoring.

Conversely, once your application has some legs to it, as stories
change due to changing requirements, you’ll find that some stories
change without ever needing to change any of the object specs.

That’s all for now.

FWIW,
David

I’m going to hijack this a bit :slight_smile:

On Jan 11, 2008 1:25 PM, David C. [email protected] wrote:

But the target of stories are system level descriptions of behaviour.
This will inevitably appear to have some overlap with the specs for
the outermost layers of the system. But when you start refactoring,
those object specifications are going to change - the system specs
(stories) should NOT. At least not as a result of refactoring.

In the first thread I linked to, I said something along the lines of
“maybe stories are better for refactoring, since you don’t have to
change them.” Examples, on the other hand, sometimes have to be
changed when refactoring, particularly if you use mocks.

However, stories are probably too slow for refactoring, and some of
the problems with refactoring with examples are simply a matter of
lacking tool support, which should eventually be fixed.

I don’t have any problem with that. I do things that way, and I get
my work done just fine. However, I’m having a tough time clarifying
my position when talking to people who believe that unit tests should
not have to change when refactoring either. I don’t think they’re
wrong, actually. It’s just a different approach and I’d like to know
how to bridge that communication gap better.

Pat

On Jan 11, 2008 1:48 PM, David C. [email protected] wrote:

On Jan 11, 2008 3:43 PM, Pat M. [email protected] wrote:

I don’t have any problem with that. I do things that way, and I get
my work done just fine. However, I’m having a tough time clarifying
my position when talking to people who believe that unit tests should
not have to change when refactoring either. I don’t think they’re
wrong, actually.

I do. If you read the refactoring book, every refactoring has a “now
change all the clients” step - tests are clients that have to be
changed. It’s just part of the deal.

That makes sense. I’ve never really thought of it that way.

The thing is that, ideally, you don’t want to have to make changes to
the tests for object A when you’re refactoring B.

WDYT?

Yeah, I buy that. Not everyone does though. Or at least not everyone
feels that it’s a particularly important goal.

Pat

On Jan 11, 2008 3:43 PM, Pat M. [email protected] wrote:

In the first thread I linked to, I said something along the lines of
“maybe stories are better for refactoring, since you don’t have to
change them.”

Keep in mind that in Java, where I think refactoring really grew in
its formality as part of the process, the tools make the changes in
your tests too. When you change a method signature the tool changes it
everywhere. I don’t recall, ever, seeing anyone complaining about
having to change tests when refactoring in java. So this is a price we
pay for the benefits of early adoption in our language of choice.

Examples, on the other hand, sometimes have to be
changed when refactoring, particularly if you use mocks.

However, stories are probably too slow for refactoring, and some of
the problems with refactoring with examples are simply a matter of
lacking tool support, which should eventually be fixed.

Right - missed this on the first read - that’s what I’m talking about
in the paragraph above.

I don’t have any problem with that. I do things that way, and I get
my work done just fine. However, I’m having a tough time clarifying
my position when talking to people who believe that unit tests should
not have to change when refactoring either. I don’t think they’re
wrong, actually.

I do. If you read the refactoring book, every refactoring has a “now
change all the clients” step - tests are clients that have to be
changed. It’s just part of the deal.

The thing is that, ideally, you don’t want to have to make changes to
the tests for object A when you’re refactoring B.

WDYT?