[rspec-users] Reusing story snippets

Ben Mabey ben at benmabey.com
Tue Jun 17 11:41:36 EDT 2008


David Chelimsky wrote:
> Reordered your posts so my comments make sense (we prefer to avoid
> top-posting - even though I sometimes violate that myself :) ).
>
>   
>> On Jun 16, 11:58 pm, Jim Morris <wolfma... at gmail.com> wrote:
>>     
>>> I'm not using Rails, I am doing end to end integration testing talking
>>> to the server via net/http, so RailsStory is not involved.
>>>       
>
> Cool. Are you talking directly through ruby constructs or through a
> browser tool like selenium?
>
>   
>>> I think the listeners may do it, I can use story_started like
>>> before(:all) and story_ended like after(:all) which will be great,
>>> presuming story_ended is always called even after a failure.
>>>       
>
> Yep.
>
>   
>>> However I am missing the place where that listener gets registered, I
>>> am using the...
>>>
>>> Story "description", %{...}, :steps_for => steps do
>>>   Scenario "sdsdsd" do
>>>   ...
>>>   end
>>> end
>>>
>>> syntax, so where is the listener set?
>>>
>>> Thanks
>>>       
>
> On Tue, Jun 17, 2008 at 2:28 AM, Jim Morris <wolfmanjm at gmail.com> wrote:
>   
>> Ahh ok think I found it...
>>
>> In my test file at the start...
>>
>> 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)
>>     
>
> Yep. That's the right way.
>
>   
>> Then I define my steps using StepGroup.new
>>     
>
> You can just use the steps_for method and it'll still work.
>
>   
>> Then the Scenarios
>>
>> It seems to work although not very intuitive :)
>>
>> I'd prefer a before(:all) and after(:all)
>>     
>
> I'm not with you on that, but I'm open :) We could solve the OP's
> problem with something like this:
>
> Before Each Scenario:
>   Log in as admin
>
> Scenario: editing private data
>   ...
>
> Before Each Scenario would match a Given step definition "Log in as
> $role" or something like that.
>
> I'm just not sure this really heads us down the right path. Next thing
> you know we'll have Before Story, After Each Scenario, After Story,
> etc and the stories are going to start looking less and less like
> stories and more and more and more like code, at which point you
> should be using example groups instead :)
>
> Anybody else have opinions about that?
>
> Cheers,
> David
>
>   
I *really* don't like the idea of having a "Before Each Scenario" or 
similar construct.  I have already seen abuses of the story runner where 
the stories look too much like code/examples.  I think adding such 
language to the story runner would really hurt and confuse the original 
intent of stories.  I'm not questioning whether such an addition would 
be helpful, I think it would and I may at times use it.. but IMO it 
would only be helpful to the developers point of view and I don't see it 
really adding much value to the stories.  If someone can offer an 
example where they think such language would help the stakeholder I 
would be interested but to me it is starting too look too much like 
examples.

Like Kyle said in a previous post, I think a better way to handle these 
situations is to rely on the fact that having an admin be logged in is 
somewhat implicit in the story and that the implementation can be 
handled under the covers, so to speak, with helper methods within the 
steps.  This of course will require you to call the same helper method 
for all of your first Given steps.  So I guess this is where the pain 
point is.. but it doesn't seem to be a big one most of the time.

The Listeners are good for application-wide/story suite wide setup and 
cleanup, like databases as such.  Placing the login of an admin into a 
listener would obviously be overkill unless all of your stories involved 
an Admin being logged in.  What people seem to asking for is more 
control over the granularity of which stories a particular listener 
effects.  Say, for example you have a set of stories that all require 
that an Admin account to exist with certain permissions and that the 
admin is logged in.  What if you could define your AdminSetupListener 
and then hook it into the runner for your stories like so:

with_steps_for(:admin_section, :webrat).and_listeners_for(:admin_setup) do
  run_story(File.expand_path(__FILE__))
end

This could provide the setup/teardown capabilities for a certain set of 
stories without polluting the Story language.

Does that make sense what I'm suggesting?  I'm not sold entirely on it 
myself.  It seems to add yet another layer of abstraction to help DRY up 
the steps and in so doing spreads the story's executable code throughout 
even more files. This could hurt maintainability so I think the use of 
this could also be abused... but if people want more granular control in 
there setup and teardown with the Stories I would vote for an option 
like this instead of placing it in the actual Story language/parser itself.

I hope most of that makes sense. :)

-Ben






More information about the rspec-users mailing list