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

Reply via email to