> > 2) Is it your goal to call "some_expensive_operation" once and only once?
Yes, exactly. In the case of the project archival spec, creating a project, archiving it, and then unzipping it to a temporary location to look at what was archived is a process that takes about 3 seconds on my machine. Since archival isn't something people will be doing live on the site, speed is not an issue from a user point of view. However, there's about 25 specs (in about a dozen sub-contexts) examining the zip output... multiply that by 3 seconds each, and that takes more time to run than all the other specs combined! I have actually managed to get this done using the method described in my blog post @ http://www.swombat.com/getting-rspec-beforeall-and-nested-contexts-w , but I have to admit it's a bit hackish. David - ":apply_to_nested => false" seems like a great way to do it, but I understand why you'd want to get the refactoring out of the way first. With my temporary hack in place, I can wait. Thanks, Daniel On Thu, Jul 9, 2009 at 3:22 PM, Zach Moazeni <zach.li...@gmail.com> wrote: > > 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@rubyforge.org >>> http://rubyforge.org/mailman/listinfo/rspec-users >>> >> >> -- >> Zach Moazeni >> http://simplechatter.com >> >> >> >> > -- > Zach Moazeni > http://simplechatter.com > > > > _______________________________________________ > rspec-users mailing list > rspec-users@rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users >
_______________________________________________ rspec-users mailing list rspec-users@rubyforge.org http://rubyforge.org/mailman/listinfo/rspec-users