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.
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 4:45 PM, Neil M. Young <ermok at tiscali.co.uk> 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: > > 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. > > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users >-------------- next part -------------- An HTML attachment was scrubbed... URL: http://rubyforge.org/pipermail/rspec-users/attachments/20080123/19f79cb3/attachment.html
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. 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 > >I''ve been running into the same issue. Ryan Davis 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
On Jan 23, 2008 10:45 PM, Neil M. Young <ermok at tiscali.co.uk> 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> 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. > > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users >
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. :) Do you understand the point I''m trying to make? -Ben aslak hellesoy wrote:> On Jan 23, 2008 10:45 PM, Neil M. Young <ermok at tiscali.co.uk> 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 > > >> 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. >> >> _______________________________________________ >> rspec-users mailing list >> rspec-users at rubyforge.org >> http://rubyforge.org/mailman/listinfo/rspec-users >> >> > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users >
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 Mabey wrote:> 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. :) > Do you understand the point I''m trying to make? > > > -Ben > > > > aslak hellesoy wrote: >> On Jan 23, 2008 10:45 PM, Neil M. Young <ermok at tiscali.co.uk> 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 >> >> >>> 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. >>> >>> _______________________________________________ >>> rspec-users mailing list >>> rspec-users at rubyforge.org >>> http://rubyforge.org/mailman/listinfo/rspec-users >>> >>> >> _______________________________________________ >> rspec-users mailing list >> rspec-users at rubyforge.org >> http://rubyforge.org/mailman/listinfo/rspec-users >> > > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-usersRegards, Kamal
On Jan 23, 2008 9:30 PM, Kamal Fariz <kamal.fariz at gmail.com> wrote:> 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?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, at 8:04 AM, Ben Mabey wrote: > > > 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. :) > > Do you understand the point I''m trying to make? > > > > > > -Ben > > > > > > > > aslak hellesoy wrote: > >> On Jan 23, 2008 10:45 PM, Neil M. Young <ermok at tiscali.co.uk> 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 > >> > >> > >>> 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. > >>> > >>> _______________________________________________ > >>> rspec-users mailing list > >>> rspec-users at rubyforge.org > >>> http://rubyforge.org/mailman/listinfo/rspec-users > >>> > >>> > >> _______________________________________________ > >> rspec-users mailing list > >> rspec-users at rubyforge.org > >> http://rubyforge.org/mailman/listinfo/rspec-users > >> > > > > _______________________________________________ > > rspec-users mailing list > > rspec-users at rubyforge.org > > http://rubyforge.org/mailman/listinfo/rspec-users > > Regards, > Kamal > > > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users >
On Jan 24, 2008 1:04 AM, Ben Mabey <ben at benmabey.com> wrote:> 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. :) > 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> > -Ben > > > > > aslak hellesoy wrote: > > On Jan 23, 2008 10:45 PM, Neil M. Young <ermok at tiscali.co.uk> 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 > > > > > >> 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. > >> > >> _______________________________________________ > >> rspec-users mailing list > >> rspec-users at rubyforge.org > >> http://rubyforge.org/mailman/listinfo/rspec-users > >> > >> > > _______________________________________________ > > rspec-users mailing list > > rspec-users at rubyforge.org > > http://rubyforge.org/mailman/listinfo/rspec-users > > > > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users >
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.
> 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 > endDidn''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 <ermok at tiscali.co.uk> wrote:> > 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.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> > > 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. > > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users >
On Jan 24, 2008 3:47 AM, Kamal Fariz <kamal.fariz at gmail.com> wrote:> > 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 > > 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?Yep. Cheers, David> > > Regards, > kamal > > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users >
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 Neil M. Young wrote:> 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 >> >> > >
On Thu, Jan 24, 2008 at 08:25:49AM +0100, aslak hellesoy wrote:> On Jan 24, 2008 1:04 AM, Ben Mabey <ben at benmabey.com> wrote: > > 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. :) > > 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 -- Marcus Ahnve Blog: http://marcus.ahnve.net