On Aug 25, 2011, at 11:40 AM, Lenny Marks wrote:
> One of the things that always annoys me when I write/use typical macros in my
> specs is how the backtrace from failures don't include the caller of the
> macro. Not a huge deal because the example name can be used to track it down,
> but I lose the ability to do things like click on the line from the backtrace
> in my IDE(I use RubyMine). I find that feature to be a nice time saver. I've
> never heard any mention of this bothering anybody so maybe I'm just being
> pedantic but tweaking things so that the actual example implementation is
> yielded by the caller seems like a better style to me because it solves that
> problem. Just curious if anybody else has any thoughts one way or the other.
> I've been leaning toward the latter when possible.
>
> Full example at:
> https://gist.github.com/1169172
>
> ex. When the example below fails, line 17 is significant
>
> 5 describe Email do
> 6 describe '.normalize', ' should strip email down to core address' do
> 7 def self.normalized(original, options)
> 8 it %{normalizes '#{original}' as '#{options[:should_be]}'} do
> 9 Email.normalize(original).should == options[:should_be]
> 10 end
> 11 end
> .....
> 16 describe 'it strips whitespace' do
> 17 normalized(' [email protected]', :should_be =>
> '[email protected]')
> 18 end
>
> Failures:
>
> 1) Email.normalize should strip email down to core address it strips
> whitespace normalizes ' [email protected]' as '[email protected]'
> Failure/Error: Email.normalize(original).should == options[:should_be]
> expected: "[email protected]"
> got: " [email protected]" (using ==)
> # org/jruby/RubyProc.java:268:in `call'
> # ./spec/lib/email_spec.rb:9:in `normalized'
> # org/jruby/RubyKernel.java:2028:in `instance_eval'
If you run this with the --backtrace flag, you should see line 17 as well.
> Compare to this where the significant lines are present in the backtrace
>
> describe Email do
> 6 describe '.normalize', ' should strip email down to core address' do
> 7 def self.normalized(original, &blk)
> 8 describe "'#{original}'" do
> 9 subject { Email.normalize(original) }
> 10 it { instance_eval(&blk) }
> 11 end
> 12 end
> ......
> 17 describe 'it strips whitespace' do
> 18 normalized(' [email protected]') { should ==
> '[email protected]' }
> 19 end
>
> Failures:
>
> 1) Email.normalize should strip email down to core address it strips
> whitespace ' [email protected]'
> Failure/Error: normalized(' [email protected]') { should ==
> '[email protected]' }
> expected: "[email protected]"
> got: " [email protected]" (using ==)
> # org/jruby/RubyProc.java:268:in `call'
> # ./spec/lib/email_spec.rb:18:in `(root)'
> # org/jruby/RubyKernel.java:2028:in `instance_eval'
> # ./spec/lib/email_spec.rb:10:in `normalized'
> # org/jruby/RubyKernel.java:2028:in `instance_eval'
Interesting that that happens. I'm not clear on why. Regardless, this macro
appraoch creates a lot of distance between the reader and the code that is
being specified. Personally, I find this much easier to read:
describe Email do
describe "#normalize" do
it "strips whitespace" do
Email.normalize(' [email protected]').should eq('[email protected]')
end
end
end
... and it would give exactly the spec output and failure message that I want.
Don't get me wrong - I'm all for sharing code where it provides a benefit that
outweighs the loss of proximity, but I would typically do that with custom
matchers, shared examples or simple helper methods (at the example level rather
than the group level).
FWIW,
David
_______________________________________________
rspec-users mailing list
[email protected]
http://rubyforge.org/mailman/listinfo/rspec-users