On 28 Feb 2009, at 21:29, Shot (Piotr Szotkowski) wrote:

I’m trying to spec a system from outside-in as an excercise in ‘emergent
design’ – and so far I love it; it made me think about the design for
two days before I even wrote the first spec… :)

Great :)

My most-outside class seems to be a prime candidate for an #each method.
The attached (stripped) spec carrying two of the approaches I came up
with passes, and raises the following quesitions – any answer would be
most appreciated!

1. A philosophical/kosherness question: In the finished system
Decomposer#each will yield Decomposition objects, but as I’m specing
from outside-in, the Decomposition class is not yet created. In the
attached example I’m using an Array as a poor man’s Decomposition
replacement. Is this a sane approach, or should I rather create
a skeletal Decomposition#initialize instead?

I think you should try to write the specs so they won't have to change when you build the real implementation. That doesn't mean creating an actual Decomposition class just yet, but it does mean that you should return something that looks enough like one for the tests to still be valid when you swap one in.

2. The first spec shows my initial approach, with a variable polling the
stuff yielded by #each and then validating its contents, but it seems
clumsy…

I think what you're finding clumsy here is the mocking setup. You don't always have to use mock objects as your 'test doubles' and often it's much easier (and leaves behind more flexible tests) if you use stubs rather than mocks.

In this case, although it's possible to create a test double for the Generators using RSpec's mocking framework, it's pretty awkward and hard to read. I would be tempted to write my own test double instead. Applying outside-in to the behaviour I want from the test double, I'd write this:
http://gist.github.com/72327

I'll leave it to you to code the #each method on the FakeGenerator, but hopefully you get the idea.

Notice that I just used an Array as the fake for @uv_gen - I might have missed something but I think that would provide an adequate double for the behaviour you had specified for the mock.

3. …so I came up with the second, Decomposer.new.to_enum approach, which simply validates the enumrator’s #next objects. Unfortunately, this does
not seem to trigger #should_receive(:each) on the *_gen mocks and made
me #stub!(:each) on them instead. Is this because I’m using RSpec 1.1.12
with Ruby 1.9.1, or am I missing something on how message expectations
work with lazy iterators (and, thus, #should_receive fail properly)?

I think you're getting too far into specifying the implementation here. I like the #each approach better.

Hope that helps.

Matt Wynne
http://blog.mattwynne.net
http://www.songkick.com

_______________________________________________
rspec-users mailing list
[email protected]
http://rubyforge.org/mailman/listinfo/rspec-users

Reply via email to