[rspec-devel] [ rspec-Feature Requests-8969 ] Evaluate "context_setup" blocks as soon as they are encountered (better compatibility with "dynamic" specs)

noreply at rubyforge.org noreply at rubyforge.org
Wed May 2 23:39:22 EDT 2007


Feature Requests item #8969, was opened at 2007-03-01 11:02
You can respond by visiting: 
http://rubyforge.org/tracker/?func=detail&atid=3152&aid=8969&group_id=797

Category: runner module
Group: None
>Status: Closed
Priority: 3
Submitted By: Lee Noori (leenoori)
Assigned to: Nobody (None)
>Summary: Evaluate "context_setup" blocks as soon as they are encountered (better compatibility with "dynamic" specs)

Initial Comment:
I'm posting this feature request as a follow-up to this mailing test post:

http://rubyforge.org/pipermail/rspec-users/2007-February/000854.html

The basic problem is that "context_setup" blocks may be run too late when setting up "dynamic" specs. The following example illustrates the problem if you have a "context_setup" block inside a context containing a dynamic specify block. Intuition might lead one to believe that it would be executed *before* the specs because it's labelled as a "setup" block and also because it appears physically before the "specify" block; however this is not the case:

context "The month march" do
   context_setup do
     @start = 1
     @max = 10
   end
   (@start.. at max).each do |n|
     specify "The root of #{n} square should be #{n}" do
       Math.sqrt(n*n).should == n
     end
   end
end

Here the "context_setup" block hasn't actually been evaluated by the time Ruby sees (and starts executing) the (@start.. at max).each block, so it doesn't work as intended. The workaround is to forget using "context_setup" and do the setup in the same scope as the following "specify" block:

context "The month march" do
   @start = 1
   @max = 10
   (@start.. at max).each do |n|
     specify "The root of #{n} square should be #{n}" do
       Math.sqrt(n*n).should == n
     end
   end
end

I suspect a robust fix would involve evaluating context_setup blocks  
as soon as they are encountered rather than deferring them until  
later.

At a minimum, the definition of the context_setup method (in lib/spec/runner/context_eval.rb) would need to be changed. Looks like the rest of the work would probably have to take place in lib/spec/runner/context.rb. I am not yet very familiar with the RSpec codebase but if one of the devs can provide some guidance I can have a shot at whipping together a patch.

----------------------------------------------------------------------

>Comment By: David Chelimsky (dchelimsky)
Date: 2007-05-03 03:39

Message:
You can do what you are looking for like this:

describe "The month march" do
  @start = 1
  @max = 10
  (@start.. at max).each do |n|
    specify "The root of #{n} square should be #{n}" do
      Math.sqrt(n*n).should == n
    end
  end
end

No need to set the vars within before(:all) (formerly context_setup).

Cheers,
David

----------------------------------------------------------------------

Comment By: David Chelimsky (dchelimsky)
Date: 2007-03-01 13:26

Message:
Hi Lee,

Thanks for posting this here rather than just on the mailing list. I have some thoughts about why I'd prefer not to do this right now, but this is the right place for any debate and to ensure that if/when the time is right we have the history.

In my view, what you're calling a workaround is actually the right way to go here. I see @start and @max as "spec generation" code, something akin to a pre-processor macro, which I would actually prefer to avoid mixing into the scope in which the spec gets executed.

On the other hand, the context_setup is intended to set up state that is expensive to set up, and therefore better off set up only once. Things like loading large data sets or starting browsers, in the case of 'spec/ui'.

To me, these are two separate concerns, which are causing confusion because they appear to be intermingled, but are never-the-less orthogonal.

The other reason is a bit more pragmatic. There have been numerous requests over time for some means of nesting contexts and/or specifications. To that end, I am exploring some alternative approaches to the inner workings of the runner, so I am hesitant to impose any new requirements on the runner right now.

Seeing as you are able to use the workaround, I'm going to defer this for now. But please feel free to keep the discussion going here while your thoughts are fresh.

Cheers,
David

----------------------------------------------------------------------

You can respond by visiting: 
http://rubyforge.org/tracker/?func=detail&atid=3152&aid=8969&group_id=797


More information about the rspec-devel mailing list