Ok here is my sugar, put in spec_helper.rb require 'rubygems' require 'spec' require 'spec/story'
# simulate before(:all) and after(:all) for stories class MyListener def set_before(&block) @before= block end def set_after(&block) @after= block end def method_missing sym, *args, &block # ignore all messages you don't care about end def story_started(title, narrative) @before.call if @before end def story_ended(title, narrative) @after.call if @after end end def setup_listener(listener) unless $my_listener Spec::Story::Runner.register_listener(listener) $my_listener= listener end end def before_story(&block) listener ||= MyListener.new listener.set_before(&block) setup_listener(listener) end def after_story(&block) listener ||= MyListener.new listener.set_after(&block) setup_listener(listener) end Use it in your story ruby file thusly... require File.join(File.dirname(__FILE__), "spec_helper") # execute this code before story runs before_story do #stuff end # execute this code after the story runs after_story do # more stuff end I'm sure it could be cleaner! On Jun 17, 4:44 pm, Jim Morris <[EMAIL PROTECTED]> wrote: > Yep thats exactly the case, an entire Story specific setup/teardown > for the Given, When Language API > > Scenario setup is obviously done in the Given, although a way to clean > up if the spec fails would be nice. > > The listener works fine for this, its just not a very intuitive way of > setting things up. However I could easily add some sugar > to my spec_helper that does the listener setup for me, basically just > wrap this... > > class MyListener > def method_missing sym, *args, &block > # ignore all messages you don't care about > end > > def story_started(title, narrative) > puts "...Started story #{title}" > end > > def story_ended(title, narrative) > puts "...Ended story #{title}" > end > end > > Spec::Story::Runner.register_listener(MyListener.new) > > On Jun 17, 3:38 pm, Ben Mabey <[EMAIL PROTECTED]> wrote: > > > Jim Morris wrote: > > > Hi, Not top posting (although I prefer it ;) > > > >> Cool. Are you talking directly through ruby constructs or through a > > >> browser tool like selenium? > > > > I have a helper that makes posts and gets and deletes and puts > > > directly to the server which is implements a mostly REST-ful API and > > > written in Java. > > > I use an Hpricot based matcher that implements have_xpath to test the > > > XML that is returned for each API call. > > > > It is a true integration test that can test the server running locally > > > or the staging server running at the Colo. > > > > I was using (and do use) Example groups for most of my integration > > > tests, however I started using Programmatic Stories (not plain text > > > stories) for a number of reasons. > > > > Firstly I prefer it looking like code so I put the whole thing in a > > > single file... > > > > steps = Spec::Story::StepGroup.new do |define| > > > define.given("user has empty bag") do > > > etc > > > > Story "test user can create, get and delete bags",...., :steps_for => > > > steps do > > > Scenario " create bag"... > > > Scenario "get bag..." > > > Scenario "delete bag..." > > > etc > > > > I prefer this because I am a programmer, it keeps things in one place > > > and makes it easy to maintain. I don't have stakeholders so plain text > > > stories are just another layer for me. Although I would use them if I > > > did have laymen stake holders. I am testing a REST-ful AJAX like API > > > to a webservice, that is used by programmers, so my stakeholders would > > > be/are programmers and again prefer programmatic code rather than > > > plain text stories. > > > > The reason I like Stories in this case, rather than Examples, is that > > > for integration testing, I can test all the edge cases for the API in > > > the most DRY-full way. The steps are coded once and I can just define > > > very thin Scenarios that test different parameters being passed in and > > > exercise all those edge cases where parameters are bad or left out > > > etc. Doing this the "old" way using Example groups was not at all DRY, > > > but worked pretty well. (Although Example groups with tons of helpers > > > maybe considered equivalent). > > > > The thing I have learned about all these BDD, TDD, XP, AGILE things > > > is to be flexible and use the best tools and practices for the job. > > > Being single minded and saying programmers can't use stories they are > > > only for stake holders means we lose a good tool! (Not that I am > > > accusing anyone of being single minded ;) > > > > Back to why I want/need these global setup/teardowns... And BDD > > > purists stop reading now ;) > > > > When doing integration testing of a remote server this way you know > > > all the tests need to have a login and a valid Sessionid in the > > > cookie. You don't want to login/logoff every Scenario because it is > > > SLOOOW. Logging in and out does not test the API other than the login > > > and logoff API and that of course has been tested once already. It is > > > not DRY to have to call login and logout in every Given, plus you need > > > it to logout even if the tests fail. And lastly (Shudder) some tests > > > have to rely on the state left by a previous test, hence the session > > > id needs to be the same, for a group of scenarios like add a resource, > > > modify the resource then delete the resource are best done as separate > > > Scenarios, relying on the previous Scenario. It would be slow and not > > > DRY to have to test add, then test add, modify, then test add, delete, > > > it is better to have Scenario add, Scenario modify, Scenario delete. I > > > know this flys in the face of SOP, but it is DRY and it is efficient > > > (ie faster) and it works! > > > > I hope that explains where I am coming from and how I (Mis-)use these > > > excellent tools you have written. > > > > Thanks > > > Jim > > > Ahh, I forgot that the original post was not dealing with plain-text > > stories. From what I understand now, you prefer the Given, When, Then > > language for your certain situation and want more flexibility to help > > DRY these programmer-only stories. That makes a lot more sense now that > > I'm reminded of the context, thanks. :) > > > When testing all the different edge cases based on different parameters > > passed in the URL I find that nested describes (example groups), like > > you mentioned, provide a good way to DRY up specs. The spec-docs also > > lend themselves well to readable docs for programmers wanting to use the > > API. When using the story framework to do this are you suggesting that > > a story be able to have setup/teardown and also have specific > > setup/teardown for individual scenarios? Or are you just suggesting > > setup/teardown for an entire story (and not the scenarios)? > > > That sounds reasonable and useful, so I hope I didn't come off sounding > > like I thought your idea was a poor one. In the context of plaintext > > stories I was thinking it would be a dangerous way to go down unless the > > language helped the stakeholder. Having more flexible setup/teardown > > for stories in general seems like a good idea that would help everyone > > though. > > > -Ben > > > _______________________________________________ > > rspec-users mailing list > > [EMAIL PROTECTED]://rubyforge.org/mailman/listinfo/rspec-users > > _______________________________________________ > rspec-users mailing list > [EMAIL PROTECTED]://rubyforge.org/mailman/listinfo/rspec-users _______________________________________________ rspec-users mailing list rspec-users@rubyforge.org http://rubyforge.org/mailman/listinfo/rspec-users