[rspec-users] Best practices for sharing state between story steps?

Jim Morris ml at e4net.com
Thu Sep 11 12:54:53 EDT 2008


Rick DeNatale wrote:

 >
 >
 > I've done something similar, but I might have handled the steps implementation a bit differently 
in that I'm not sure my approach would be called stateless.
 >
 > For example say I had (in a very abstract form)
 >
 >     Given 'Rick' has admin privileges
 >     Then 'Rick' can do admin function X
 >
 > In the  step for the given, I'd get or create an admin user named rick, and set an instance 
variable say @admin
 > Then in the step for the then, I'd have an expectation that the name of @admin matched the name 
given in the step.
 > This was a way of catching cases where the story mixed up actors.
 >
 > Although the short example doesn't really emphasize the problem I was trying to solve, I'm not 
sure in retrospect whether or not this was a valuable thing to do.

I like this discussion because it shows the ways different people have solved a very practical problem.

I don't think what you describe is "bad", I do something very similar with my integration tests that 
test a RESTFUL API based web service that returns XML to requests.

I use Hpricot to test the responses, but as this is not rails, I have to store the response between 
steps.

A contrived Example...

Scenario "test get resource list"
   Given "database has 10 resources
   When "request made to list resources"
   Then "10 resources are returned"

In my case the Given actually clears the resource table and populates it with 10 resources, I access 
the database directly using the Sequel Gem, however if the database is remote this is problematic.

The When makes the RESTful request via http. and captures the result as an Hpricot object.
The When step looks something like this...

   When "..." do
    resp = @req_http.post(path, params, headers)

     if resp.code != "200"
       raise "#{resp.code} #{resp.message}"
     end

     @hdoc = Hpricot.XML(resp.body)
   end

The Then step looks something like this...

   Then "$cnt resources are returned" do |cnt|
     @hdoc.should have_xpath("/resources", :count => cnt)
     @hdoc.should have_xpath("/resources/resource[@id='1']")
     @hdoc.should have_xpath("/resources/resource[@id='2']")
     ...etc...
   end

I have a custom hpricot matcher which provides the have_xpath matcher

Yes this is stateful, but the @hdoc variable is central to the tests and I don't see any other way 
to carry the response from the When to the Then, unless you combine the step in a then and skip the 
when, so you don't have to carry state across the steps, but I prefer the first method as I can run 
more tests on the returned document.

e.g.
   Then "requesting a list of resources returns 10 items"


-- 
Jim Morris, http://blog.wolfman.com Rick DeNatale wrote:


More information about the rspec-users mailing list