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(' j...@somewhere.com', :should_be => > 'j...@somewhere.com') > 18 end > > Failures: > > 1) Email.normalize should strip email down to core address it strips > whitespace normalizes ' j...@somewhere.com' as 'j...@somewhere.com' > Failure/Error: Email.normalize(original).should == options[:should_be] > expected: "j...@somewhere.com" > got: " j...@somewhere.com" (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(' j...@somewhere.com') { should == > 'j...@somewhere.com' } > 19 end > > Failures: > > 1) Email.normalize should strip email down to core address it strips > whitespace ' j...@somewhere.com' > Failure/Error: normalized(' j...@somewhere.com') { should == > 'j...@somewhere.com' } > expected: "j...@somewhere.com" > got: " j...@somewhere.com" (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(' j...@somewhere.com').should eq('j...@somewhere.com') 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 rspec-users@rubyforge.org http://rubyforge.org/mailman/listinfo/rspec-users