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@rubyforge.org
http://rubyforge.org/mailman/listinfo/rspec-users
--
Zach Moazeni
http://simplechatter.com
_______________________________________________
rspec-users mailing list
rspec-users@rubyforge.org
http://rubyforge.org/mailman/listinfo/rspec-users