[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
once?
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
http://simplechatter.com
More information about the rspec-users
mailing list