[rspec-users] before(:all) and nested contexts

Zach Moazeni zach.lists at gmail.com
Thu Jul 9 10:22:53 EDT 2009

Rereading your original email, I'm thinking I may not have entirely  
understood your situation.

1) Looks like you've already defined the  
"some_expensive_operation" (but that's minor)

2) Is it your goal to call "some_expensive_operation" once and only  

On Jul 9, 2009, at 10:18 AM, Zach Moazeni wrote:

> Hey Dan,
> 1 approach you could do is define a method within the outer describe  
> that is called within the inner describe and within each test not  
> contained by an inner describe.
> describe "Some functionality" do
>  it "should do something" do
>    @variable = some_expensive_operation
>    @variable.should do_something
>  end
>  describe "in a specific context" do
>    before(:all) do
>      @variable = some_expensive_operation
>    end
>    it "should do another thing" do
>      @variable.should do_another_thing
>    end
>  end
>  def some_expensive_operation
>    p "in here"
>  end
> end
> (also uploaded to http://gist.github.com/143693)
> My solution is to unDRY the subcontext's preconditions. I have  
> pretty strong opinions about DRYing up specs at the cost of  
> grokability.
> On Jul 9, 2009, at 6:40 AM, Daniel Tenner wrote:
>> Hi all,
>> Like everyone (?), I use nested contexts to keep my specs well  
>> organised and tidy.
>> However, I have a problem. I have various sets of specs that needs  
>> to perform very time-expensive operations to set up the fixtures  
>> that will be examined in the tests. Two specific examples: testing  
>> access control logic (requires creating a whole tree of items to  
>> verify the correct access level against each item), and project  
>> archival (which creates a project, fills it with test data,  
>> archives/zips the project contents, then unzips them for  
>> examination).
>> I tried using before(:all) to set up those costly fixtures, however  
>> I hit upon a feature of rspec that made that less than successful:
>> When using before(:all) along with nested contexts, rspec actually  
>> re-runs the before(:all) before each sub-context. So if, like me,  
>> you have your specs neatly organised in sub-contexts, the  
>> before(:all) is actually re-run many times.
>> Interestingly, when a before(:all) is run in the root context,  
>> rspec does not actually remove the data from the database when re- 
>> running the before(:all). "Great," I then thought, "I can just  
>> detect whether the data is created and decide whether or not to  
>> create the objects on that basis". Not so fast, though: Rspec may  
>> not clobber the database, but it does clobber instance variables.  
>> In the case of the access control test, there's about 40 different  
>> instance variables, so keeping track of them all manually in some  
>> global variable outside of rspec would be messy to say the least...
>> So my question is, is there any workaround for successfully using  
>> before(:all) and nested specs, so that code like the following  
>> works and doesn't run the expensive operation more than once:
>> describe "Some functionality" do
>>  before(:all) do
>>    @variable = some_expensive_operation
>>  end
>>  it "should do something" do
>>    @variable.should do_something
>>  end
>>  describe "in a specific context" do
>>    it "should do another thing" do
>>      @variable.should do_another_thing
>>    end
>>  end
>> end
>> Worth noting that I'm quite happy to give up the ability to have  
>> before blocks in the sub-contexts in order to ensure that the  
>> expensive operation is only run once...
>> Your thoughts most welcome... (including, perhaps, telling me that  
>> I'm Doing It Wrong)
>> Daniel Tenner
>> http://www.woobius.com
>> http://danieltenner.com
>> _______________________________________________
>> rspec-users mailing list
>> rspec-users at rubyforge.org
>> http://rubyforge.org/mailman/listinfo/rspec-users
> --
> Zach Moazeni
> http://simplechatter.com

Zach Moazeni

More information about the rspec-users mailing list