[rspec-users] Name collision - how would you handle this?

David Chelimsky dchelimsky at gmail.com
Sun Aug 8 11:27:53 EDT 2010


On Aug 8, 2010, at 8:05 AM, Ashley Moran wrote:

> On 8 Aug 2010, at 12:05, Matt Wynne wrote:
> 
>>> And you override it using let(:foo), which would be a perfectly reasonable way to handle it. In fact, it would be the way I would handle in instinctively, because now I don't have to wrote my own memoization handling into the method.
>> 
>> I instinctively agree with ashley, but I see your point too David.
>> 
>> Would it be awful to make let even more magic, and do something with #caller to forward the message to MiniTest if it didn't come from the code in your example block? Maybe the method defined by let could even have a __hidden name, and then RSpec can forward the message to that __hidden method if the message was sent from within the example block.
>> 
>> Sounds pretty horrible, doesn't it?

Yes! It seems crazy to me to put this burden on RSpec, or any downstream library. The problem here stems from the fact that Minitest consumed a non-testing-domain-specific name here. Test::Unit uses build_message, which is still sort of generic, but at least it's a verb. I submitted a request to change message to build_message [1], but even if Ryan agrees to do it, we wouldn't likely see it in ruby-1.9.2, so we'd still have the conflict for some time.

Also, let's say he does agree - now people who like to prefix their test-data-building-helper-methods with build_xxx will be screwed too :)

I wonder if the right answer is for RSpec to implement its own base assertion library, matching the Test::Unit/Minitest assertion APIs. That would have an interesting side effect in that domain-specific assertion-libraries could be used in RSpec without having to depend on Test::Unit or Minitest. It would also allow folks who like RSpec's structure (example groups and examples) but prefer assert_xxx over RSpec's matcher to use RSpec the way they'd like without the additional dependency.

Thoughts on this? Really just an idea. I'm fairly convinced it's a bad one, but my head is sort of spinning over this issue right now (or maybe it's the cocktails at http://thedrchicago.com/), so I figured I'd throw it against the wall and see if it sticks (think spaghetti, or Jackson Pollock).

> Hmmm, sounds like it could create a pretty nasty coupling to MiniTest.  Maybe there's a general solution like:
> 
>  define_example_method do # or maybe "define_helper" ?
>    # some stuff that only gets called from examples
>  end
> 
> I'm not sure I'd be keen on let embedding this magic, but maybe as a general concept it makes more sense, as a way of isolating helper code in example groups.

This suggests, to me, "don't use Ruby if you want things to work right."

> There's another side to the debate, which is that in shared example groups, I prefer the precondition-check style to the templatemethod-fail style, ie rather than:
> 
>  def foo
>    raise "you need to define a foo method ..."
>  end
> 
> I'd prefer to write:
> 
>  unless respond_to?(:foo)
>    raise "you need to define a foo method ..."
>  end
> 
> But that would involve evaluating the configuration block first >:)

Keep in mind that it_should_behave_like generates a nested group, so shared group authors _can_ do this:

shared_examples_for "bar" do
  unless respond_to?(:foo)
    raise "gotta have foo"
  end
end

and host group authors can do this:

describe "thing" do
  let(:foo) { Foo.new }
  it_should_behave_like "bar"
end

That's part of the beauty of eval'ing the conditions block last - we get the best of both worlds.

Cheers,
David

[1] http://rubyforge.org/tracker/index.php?func=detail&aid=28457&group_id=1040&atid=4097

> 
> Ash
> 
> -- 
> http://www.patchspace.co.uk/
> http://www.linkedin.com/in/ashleymoran



More information about the rspec-users mailing list