[rspec-users] [rspec-rails] For helper specs, why is the helper cached in the class between running each example?

David Chelimsky dchelimsky at gmail.com
Mon Feb 8 20:33:23 EST 2010


On Mon, Feb 8, 2010 at 9:31 PM, Myron Marston <myron.marston at gmail.com> wrote:
> Thanks, David.  I searched the google group for discussions of my
> problem but forgot to search the github issues.  I'll be sure to check
> there next time!

No worries - I was just surprised that this has been a theoretical
problem for so long and three people bring it up within a week of each
other! Glad we got it visible and fixed.

Cheers,
David

>
> On Feb 8, 5:17 pm, David Chelimsky <dchelim... at gmail.com> wrote:
>> On Mon, Feb 8, 2010 at 1:44 PM, Myron Marston <myron.mars... at gmail.com> wrote:
>> > I ran into a recent problem writing specs for a helper.  I was testing
>> > a helper that uses the standard memoization technique of caching the
>> > result of an expensive calculation in an instance variable:
>>
>> >  def something_expensive
>> >    @something_expensive ||= do_something_expensive
>> >  end
>>
>> > I have several different rspec examples for this one helper method,
>> > all of which mock out a method that do_something_expensive calls,
>> > which should in turn cause a different return value from
>> > #something_expensive.  When I ran my specs, I wound up getting the
>> > same return value for each spec--the return value from the first spec
>> > that ran.  After investigating it a bit, I ran across this[1] code in
>> > rspec-rails' ExampleHelperGroup:
>>
>> >        def helper
>> >          self.class.helper
>> >        end
>>
>> > The #helper method simply delegates to the class's helper method,
>> > which memoizes the helper object in an instance variable.  The result
>> > of this is that the helper is cached in the class between example
>> > runs, and because of the memoization in my helper method, subsequent
>> > specs were returning the same value.
>>
>> > I found a work around:
>>
>> >    after(:each) do
>> >      helper.instance_variable_set('@something_expensive', nil)
>> >    end
>>
>> > But it feel like a bit of a hack, and it's annoying/frustrating that I
>> > have to do this.  My specs shouldn't have to be aware of the
>> > memoization and manually clear it to work.
>>
>> > Why is the helper object cached in the class between running each
>> > example?  This can accidentally lead to spec interdependencies (i.e.
>> > example B only passes if it runs after example A has run, because
>> > example A puts the helper object into a certain state that example B
>> > unknowingly depends on).
>>
>> Someone just submitted a ticket w/ a patch on this last week:
>>
>> https://rspec.lighthouseapp.com/projects/5645-rspec/tickets/627
>>
>> It'll be released with rspec-rails-1.3.3, some time in the next few days.
>>
>> Cheers,
>> David
>>
>>
>>
>> > Thanks,
>> > Myron
>>
>> > [1]http://github.com/dchelimsky/rspec-rails/blob/1.3.2/lib/spec/rails/ex...
>> > _______________________________________________
>> > rspec-users mailing list
>> > rspec-us... at rubyforge.org
>> >http://rubyforge.org/mailman/listinfo/rspec-users
>>
>> _______________________________________________
>> rspec-users mailing list
>> rspec-us... at rubyforge.orghttp://rubyforge.org/mailman/listinfo/rspec-users
> _______________________________________________
> rspec-users mailing list
> rspec-users at rubyforge.org
> http://rubyforge.org/mailman/listinfo/rspec-users
>


More information about the rspec-users mailing list