DRYing up stories

I’m finding that I’m writing sets of very similar scenarios to check
access
permissions for each of my actions. Does anyone have suggestions on how
to
dry this up:

Given an existing Account
And a logged in Admin
When the user visits account/manage
Then he should get access

Given an existing Account
And a logged in Manager
When the user visits account/manage
Then he should get access

Given an existing Account
And a logged in Supervisor
When the user visits account/manage
Then he should not get access

Given an existing Account
And a logged in Reviewer
When the user visits account/manage
Then he should not get access

Given an existing Account
And a logged in User
When the user visits account/manage
Then he should not get access


View this message in context:
http://www.nabble.com/DRYing-up-stories-tp15053384p15053384.html
Sent from the rspec-users mailing list archive at Nabble.com.

Neil M. Young wrote:

And a logged in Manager
When the user visits account/manage
Then he should not get access

Given an existing Account
And a logged in User
When the user visits account/manage
Then he should not get access

I’ve been running into the same issue. Ryan D. came up with the idea
of a “functional test matrix”:
http://blog.zenspider.com/archives/2007/04/functional_test_matrix.html
borrowing the spreadsheet idea from FIT… Anyways, I have been trying to
think of a way to apply something similar in conjunction with stories…
Maybe generate and run stories based off a matrix for access control
reasons?

Does this give any one some ideas?

-Ben

Do all of these scenarios exist in the same story?
Should they be dried up?
Would Clarity over Cleverness apply here?

On Jan 23, 2008 10:45 PM, Neil M. Young [email protected] wrote:

I’m finding that I’m writing sets of very similar scenarios to check access
permissions for each of my actions. Does anyone have suggestions on how to
dry this up:

Beware that DRY has a cost. Clarity and readability.

David’s BDD manifesto (slightly rephrased):

We prefer clarity over DRY (that is - while there is value in DRYness,
we value clarity more)

Aslak

While the original post had DRY in the subject line I don’t see this as
a DRY issue. I see it as a visualization and maintenance issue. If I
add a new role and I want to test each action for it’s permissions it
would be much easier for a customer to go down a spread sheet and
designate within each cell what the response should be… success or
failure, etc… This would give the customer a bird’s eye view of
permissions for the entire app for each class of users. By using a
separate scenario for each role in each story you will be creating a lot
of copy and past work which will comminucate the same information a
spreadsheet would but a lot more inefficently since someone would have
to read hundreds of pages of stories. I love the plain text stories.
We just have to remember that there are better ways to express large
amounts of data than plain English. :slight_smile:
Do you understand the point I’m trying to make?

-Ben

Slightly OT, but what can be done to DRY up steps? For aesthetics and
more natural sounding stories, I often have things like

Given a user in the system

and

Given 2 users in the system

where the small change is in the pluralization. What I currently do is
to have two steps that essentially do the same thing (of course,
converting ‘a’ to 1 before that). How can one alias a step?

On Jan 24, 2008, at 8:04 AM, Ben M. wrote:

of copy and past work which will comminucate the same information a

Given an existing Account
And a logged in User
http://rubyforge.org/mailman/listinfo/rspec-users
[email protected]
http://rubyforge.org/mailman/listinfo/rspec-users

Regards,
Kamal

On Jan 23, 2008 9:30 PM, Kamal F. [email protected] wrote:

to have two steps that essentially do the same thing (of course,
converting ‘a’ to 1 before that). How can one alias a step?

With 1.1.1 you can do this:

Given “$n_users in the system” do |num_users|
case num_users
when “a user”
# one user case
when /(\d*) users/
# multi user case using $1
end
end

With 1.1.2 you can do this:

Given /(a|\d*) users? in the system/ do |num_users|
num_users = (num_users == ‘a’) ? 1 : num_users.to_i
(1…num_users).each do

end
end

HTH,
David

On Jan 24, 2008 1:04 AM, Ben M. [email protected] wrote:

to read hundreds of pages of stories. I love the plain text stories.
We just have to remember that there are better ways to express large
amounts of data than plain English. :slight_smile:
Do you understand the point I’m trying to make?

I totally get your point. This is where FIT shines (or maybe Ryan’s
Matrix).

Aslak

With 1.1.2 you can do this:

Given /(a|\d*) users? in the system/ do |num_users|
num_users = (num_users == ‘a’) ? 1 : num_users.to_i
(1…num_users).each do

end
end

Didn’t know you could do that! Thanks. So, the step will yield all the
matches in the same order regexp will populate the matches array?

Regards,
kamal

On Jan 24, 2008 2:25 AM, Neil M. Young [email protected] wrote:

:admin => new_admin,

#log user in
get @url
response.should redirect_to("not_authorised")

end
end

any major BDD violations there? I personally don’t mind the somewhat complex
steps because as Ben pointed out, the plain text stories are more manageable
this way and still very readable.

I think I’d rather have the first step be explicit about the different
types:

Given users in the Manager, Admin, Supervisor and Anonymous roles
When they visit account/manage
Then only Admins and Managers should get access

As for the complexity within the steps, there’s a balance to be found
between that and clarity of the steps in the scenario (Given blah de
blah). The underlying principle should be that you or anyone on your
team should be able to quickly understand a failure. As soon as you
start debugging steps to understand a failure, those steps are losing
part of their value.

Where that leads you is going to vary from person to person, team to
team. For me, personally, my only beef with the Then step definition
here is that I wouldn’t likely be able to know which role caused the
failure. Otherwise I don’t feel there is a fundamental BDD violation.

FWIW,
Cheers,
David

some interesting viewpoints so far. How do people feel about something
like
this:

Given every type of user
When they visit account/manage
Then only Admins and Managers should get access

Given(“every type of user”) do
@users = {
:admin => new_admin,
:manager => new_manager,
:supervisor => new_supervisor,
:reviewer => new_reviewer,
:user => new_user
}
end

When(“they visit $url”) do |url|
@url = url
end

Then(“only $allow_list should get access”) do |allow_list|
allow_list = allow_list.split(’ and ').collect {|x|
x.downcase.singularize.intern}
allow_list.each do |x|
user = @users.delete(x)
# log user in
get @url
response.should_not be_redirect
end
@users.each do |x|
#log user in
get @url
response.should redirect_to(“not_authorised”)
end
end

any major BDD violations there? I personally don’t mind the somewhat
complex
steps because as Ben pointed out, the plain text stories are more
manageable
this way and still very readable.

Neil M. Young wrote:

I’m finding that I’m writing sets of very similar scenarios to check
access permissions for each of my actions.

snip


View this message in context:
http://www.nabble.com/DRYing-up-stories-tp15053384p15060580.html
Sent from the rspec-users mailing list archive at Nabble.com.

On Jan 24, 2008 3:47 AM, Kamal F. [email protected] wrote:

matches in the same order regexp will populate the matches array?
Yep.

Cheers,
David

I actually really like this idea. Very neat. Like David said the only
problem might be being able to see where the failure occurred. I think
that this problem could be solved or at least mitigated with some sort
of custom matcher though (maybe even a simple one.)
This solves the baseline case for me. The other problem I am having is
that based on a certain model’s settings the type of user’s who have
access to it varies. So I could just add an additional Given describing
that condition… but I may still have a combinatorial explosion on the
amount of stories needed to explain every case… But I think this
approach will work nicely for the time being so I’ll try it out. Thanks
for the idea.

-Ben

On Thu, Jan 24, 2008 at 08:25:49AM +0100, aslak hellesoy wrote:

spreadsheet would but a lot more inefficently since someone would have
to read hundreds of pages of stories. I love the plain text stories.
We just have to remember that there are better ways to express large
amounts of data than plain English. :slight_smile:
Do you understand the point I’m trying to make?

I totally get your point. This is where FIT shines (or maybe Ryan’s Matrix).

I completely agree. My experience is that you most often end up with two
types of specs: flows and rules. Flows are best described in a story
format, whereas rules are best described in a clear table format.

Just take a simple password rule. Using flows to do this is overly
verbose compared to fit. For example:

|password|valid?|
|short |false |
|allchars|false |
|goo0d1ne|true |

And of course flows are not well documented using Fit. That is my basic
theory for why it never took of.

I have spent an hour or two trying to write a story runner for Fit, so
far mostly reading the arcane Ruby Fit library. I’ll get back when I
have something to show.

/Marcus