Best practices for sharing state between story steps?

Rick DeNatale wrote:

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”

of course, there’s one ‘global’ shared between steps that we cant
live without: response
:slight_smile:

On Tue, Sep 9, 2008 at 8:42 AM, aslak hellesoy
[email protected]wrote:

On Tue, Sep 9, 2008 at 2:21 PM, Dan N. [email protected] wrote:

Hi Jim.

I guess I’m not a purist then - that looks fine to me, and it’s probably
something I would consider doing too.

Having experienced this pain in one project, I decided to try out

http://github.com/aslakhellesoy/ba/tree/master/features/submit_proposal.feature

You can see the extra verbosity I’m talking about in the repetition of
“Aslak”, “Beerfest” etc.

I’m still pragmatic about this of course, but now you know some of my
experience.

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.


Rick DeNatale

My blog on Ruby
http://talklikeaduck.denhaven2.com/

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”