List, Quick question about Cucumber/Gherkin. I''m considering adding ''With'' as a step definition to support scenarios like: Given a policy With a PCF practice state And a secondary risk ... I''m fairly new to ruby - but I can''t quite get this one figured out. I''ve tried adding Cucumber.alias_steps ([''With'']) To my features/support/env.rb file, but when I run cucumber, I still get a Syntax error. It looks like my ''with'' never gets added to the original list. Suggestions? -- Tim Hart Senior Software Engineer PICA Group 615-713-9956 :cell timothyjhart :Y! tjhart at me.com :AIM ***************************************************************************** Disclaimer: This electronic message may contain information that is Confidential or legally privileged. It is intended only for the use of the individual(s) and entity named in the message. If you are not an intended recipient of this message, please notify the sender immediately and delete the material from your computer. Do not deliver, distribute or copy this message and do not disclose its contents or take any action in reliance on the information it contains. *****************************************************************************
List, Quick question about Cucumber/Gherkin. I''m considering adding ''With'' as a step definition to support scenarios like: Given a policy With a PCF practice state And a secondary risk ... I''m fairly new to ruby - but I can''t quite get this one figured out. I''ve tried adding Cucumber.alias_steps ([''With'']) To my features/support/env.rb file, but when I run cucumber, I still get a Syntax error. It looks like my ''with'' never gets added to the original list. Suggestions? -- Tim Hart Senior Software Engineer PICA Group 615-713-9956 :cell timothyjhart :Y! tjhart at me.com :AIM ***************************************************************************** Disclaimer: This electronic message may contain information that is Confidential or legally privileged. It is intended only for the use of the individual(s) and entity named in the message. If you are not an intended recipient of this message, please notify the sender immediately and delete the material from your computer. Do not deliver, distribute or copy this message and do not disclose its contents or take any action in reliance on the information it contains. *****************************************************************************
On Fri, Mar 13, 2009 at 10:28 PM, Tim Hart <THart at picagroup.com> wrote:> List, > > Quick question about Cucumber/Gherkin. > > I''m considering adding ''With'' as a step definition to support scenarios > like: > > Given a policy > With a PCF practice state > And a secondary risk > ... > > I''m fairly new to ruby - but I can''t quite get this one figured out. I''ve > tried adding > > Cucumber.alias_steps ([''With'']) > > To my features/support/env.rb file, but when I run cucumber, I still get a > Syntax error. It looks like my ''with'' never gets added to the original list. >Unfortunately, this only aliases the ruby methods (this will let you call With /some step/ do..end in a step definition ruby file. In order to make the plain text parser recognise other words, a change is needed in languages.yml. If you add a feature request in Lighthouse I''ll see if I can add it. Cheers, Aslak> > Suggestions? > -- > Tim Hart > Senior Software Engineer > PICA Group > 615-713-9956 :cell > timothyjhart :Y! > tjhart at me.com :AIM > > > ***************************************************************************** > > Disclaimer: This electronic message may contain information that is > Confidential or legally privileged. It is intended only for the use of the > individual(s) and entity named in the message. If you are not an intended > recipient of this message, please notify the sender immediately and delete > the material from your computer. Do not deliver, distribute or copy this > message and do not disclose its contents or take any action in reliance on > the information it contains. > > > ***************************************************************************** > > > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users >-- Aslak (::) -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://rubyforge.org/pipermail/rspec-users/attachments/20090313/642a4949/attachment.html>
On 13 Mar 2009, at 21:47, aslak hellesoy wrote:> > > On Fri, Mar 13, 2009 at 10:28 PM, Tim Hart <THart at picagroup.com> > wrote: > List, > > Quick question about Cucumber/Gherkin. > > I''m considering adding ''With'' as a step definition to support > scenarios like: > > Given a policy > With a PCF practice state > And a secondary risk > ... > > I''m fairly new to ruby - but I can''t quite get this one figured out. > I''ve tried adding > > Cucumber.alias_steps ([''With'']) > > To my features/support/env.rb file, but when I run cucumber, I still > get a Syntax error. It looks like my ''with'' never gets added to the > original list. > > Unfortunately, this only aliases the ruby methods (this will let you > call With /some step/ do..end in a step definition ruby file. > In order to make the plain text parser recognise other words, a > change is needed in languages.yml. > > If you add a feature request in Lighthouse I''ll see if I can add it.I''m not sure if I like this - dependency between steps seems like a dodgy road to go down. When you''re in a step definition, how would you know what object the ''With'' was referring to? Matt Wynne http://blog.mattwynne.net http://www.songkick.com
Den 14. mars. 2009 kl. 13.59 skrev Matt Wynne <matt at mattwynne.net>:> > On 13 Mar 2009, at 21:47, aslak hellesoy wrote: > >> >> >> On Fri, Mar 13, 2009 at 10:28 PM, Tim Hart <THart at picagroup.com> >> wrote: >> List, >> >> Quick question about Cucumber/Gherkin. >> >> I''m considering adding ''With'' as a step definition to support >> scenarios like: >> >> Given a policy >> With a PCF practice state >> And a secondary risk >> ... >> >> I''m fairly new to ruby - but I can''t quite get this one figured >> out. I''ve tried adding >> >> Cucumber.alias_steps ([''With'']) >> >> To my features/support/env.rb file, but when I run cucumber, I >> still get a Syntax error. It looks like my ''with'' never gets added >> to the original list. >> >> Unfortunately, this only aliases the ruby methods (this will let >> you call With /some step/ do..end in a step definition ruby file. >> In order to make the plain text parser recognise other words, a >> change is needed in languages.yml. >> >> If you add a feature request in Lighthouse I''ll see if I can add it. > > I''m not sure if I like this - dependency between steps seems like a > dodgy road to go down. > > When you''re in a step definition, how would you know what object the > ''With'' was referring to? >Good question Matt. Let''s clarify this first. Maybe there is a better way to express this with the current language. Aslak> Matt Wynne > http://blog.mattwynne.net > http://www.songkick.com > > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users
On Mar 14, 2009, at 8:49 AM, "Aslak Helles?y" <aslak.hellesoy at gmail.com> wrote:> > > Den 14. mars. 2009 kl. 13.59 skrev Matt Wynne <matt at mattwynne.net>: > >> >> On 13 Mar 2009, at 21:47, aslak hellesoy wrote: >> >>> >>> >>> On Fri, Mar 13, 2009 at 10:28 PM, Tim Hart <THart at picagroup.com> >>> wrote: >>> List, >>> >>> Quick question about Cucumber/Gherkin. >>> >>> I''m considering adding ''With'' as a step definition to support >>> scenarios like: >>> >>> Given a policy >>> With a PCF practice state >>> And a secondary risk >>> ... >>> >>> >>> >>> >>> Unfortunately, this only aliases the ruby methods (this will let >>> you call With /some step/ do..end in a step definition ruby file. >>> In order to make the plain text parser recognise other words, a >>> change is needed in languages.yml. >>> >>> If you add a feature request in Lighthouse I''ll see if I can add it. >> >> I''m not sure if I like this - dependency between steps seems like a >> dodgy road to go down. >> >> When you''re in a step definition, how would you know what object the >> ''With'' was referring to? >> > > Good question Matt. Let''s clarify this first. Maybe there is a better > way to express this with the current language. >>As a test, I removed the ''add alias'' line from my env.rb file, and updated languages.yaml. I updated the line that read and: And To read and: And|With Then my step_definition file can have a step definition like Given /a PCF Practice state/ do ... end Which I''d exactly what I was looking for. My only concern I''d that I''d like to be able to add the ''With'' to the language through code instead of having to update the yaml file. That way I have the option of varying the language for specific projects without having to ''polute'' the basic language globally. I assumed this was what the ''add_alias'' function would do for me in the first place. ***************************************************************************** Disclaimer: This electronic message may contain information that is Confidential or legally privileged. It is intended only for the use of the individual(s) and entity named in the message. If you are not an intended recipient of this message, please notify the sender immediately and delete the material from your computer. Do not deliver, distribute or copy this message and do not disclose its contents or take any action in reliance on the information it contains. *****************************************************************************
On Sat, Mar 14, 2009 at 5:59 AM, Matt Wynne <matt at mattwynne.net> wrote:> I''m not sure if I like this - dependency between steps seems like a dodgy > road to go down.I''m wondering how you''d feel about a style I''ve adopted: Scenario: Accepting a direct challenge, without leaving a comment Given there is a challenge And I am logged in And I have been invited to that challenge When I visit the challenge''s page And I press "Accept" Then I should go to my attempt detail page for the challenge And I should see that I accepted the challenge And I should not see "Attempt Challenge" Clearly, there is dependency between steps - each has to know what challenge they''re working on, for one thing. But I''ve found that it reads better than the alternative Given there is a challenge call ''Reach from the Stars'' for ''Halo 3'' And I am logged in as Mark And Mark was invited to ''Reach from the Stars'' for ''Halo 3'' on ''Sept 1, 2009'' by ''Bill'' When I visit the challenge page for ''Reach from the Stars for ''Halo 3'' And I press "Accept" Then I should go to Mark''s attempt detail page for the challenge ''Reach from the Stars'' for ''Halo 3'' And I should see that ''You accepted this challenge on Sept 1, 2009'' And I should not see "Attempt Challenge" The first one reads more like a business-level story to me and the second one reads more like a test. Thoughts? ///ark
Is the syntax you''re using a misreading of the wiki advice on Feature-Coupled Steps. Why not have "GIven a policy with a PCF practice state and seconday risk" This is not a featured coupled step because PCF practice state and secondary risk are part of the Policies state and are not seperate. Seperating the step as you have done does not reduce coupling. In fact all it does is complicate the steps because a variable containing the policy has to now be in the 3 steps. Perhaps the need for a with is a ''smell'' suggesting that you are seperating a step that is intrinsically coupled. So with really shouldn''t be needed at all. HTH Andrew 2009/3/13 Tim Hart <THart at picagroup.com>> List, > > Quick question about Cucumber/Gherkin. > > I''m considering adding ''With'' as a step definition to support scenarios > like: > > Given a policy > With a PCF practice state > And a secondary risk > ... > > I''m fairly new to ruby - but I can''t quite get this one figured out. I''ve > tried adding > > Cucumber.alias_steps ([''With'']) > > To my features/support/env.rb file, but when I run cucumber, I still get a > Syntax error. It looks like my ''with'' never gets added to the original list. > > Suggestions? > -- > Tim Hart > Senior Software Engineer > PICA Group > 615-713-9956 :cell > timothyjhart :Y! > tjhart at me.com :AIM > > > ***************************************************************************** > > Disclaimer: This electronic message may contain information that is > Confidential or legally privileged. It is intended only for the use of the > individual(s) and entity named in the message. If you are not an intended > recipient of this message, please notify the sender immediately and delete > the material from your computer. Do not deliver, distribute or copy this > message and do not disclose its contents or take any action in reliance on > the information it contains. > > > ***************************************************************************** > > > _______________________________________________ > 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/20090314/1345cfc3/attachment.html>
On 14 Mar 2009, at 15:50, Mark Wilden wrote:> On Sat, Mar 14, 2009 at 5:59 AM, Matt Wynne <matt at mattwynne.net> > wrote: > >> I''m not sure if I like this - dependency between steps seems like a >> dodgy >> road to go down. > > I''m wondering how you''d feel about a style I''ve adopted: > > Scenario: Accepting a direct challenge, without leaving a comment > Given there is a challenge > And I am logged in > And I have been invited to that challenge > When I visit the challenge''s page > And I press "Accept" > Then I should go to my attempt detail page for the challenge > And I should see that I accepted the challenge > And I should not see "Attempt Challenge" > > Clearly, there is dependency between steps - each has to know what > challenge they''re working on, for one thing. But I''ve found that it > reads better than the alternative > > Given there is a challenge call ''Reach from the Stars'' for ''Halo 3'' > And I am logged in as Mark > And Mark was invited to ''Reach from the Stars'' for ''Halo 3'' on > ''Sept 1, 2009'' by ''Bill'' > When I visit the challenge page for ''Reach from the Stars for > ''Halo 3'' > And I press "Accept" > Then I should go to Mark''s attempt detail page for the challenge > ''Reach from the Stars'' for ''Halo 3'' > And I should see that ''You accepted this challenge on Sept 1, > 2009'' And I should not see "Attempt Challenge" > > The first one reads more like a business-level story to me and the > second one reads more like a test.Totally agree with this, and I do it all the time. On my team we allow ourselves to use the term ''the Widget'' to mean Widget.first, but we''ll always assert Widget.count.should == 1 when we do. We also have a nifty little convention that allows us to talk about ''the Widget "Foo"'' and ''the Widget "Bar"'' because pretty much every entity in our domain (or at least the ones we refer to like this in our features) has a #name attribute. Matt Wynne http://blog.mattwynne.net http://www.songkick.com
On Sat, Mar 14, 2009 at 1:33 PM, Matt Wynne <matt at mattwynne.net> wrote:> We also have a nifty little convention that allows us to talk about ''the > Widget "Foo"'' and ''the Widget "Bar"'' because pretty much every entity in our > domain (or at least the ones we refer to like this in our features) has a > #name attribute.That sounds like a great way to avoid the instance variable. ///ark
On Mar 14, 2009, at 3:38 PM, "Andrew Premdas" <apremdas at gmail.com<mailto:apremdas at gmail.com>> wrote: Is the syntax you''re using a misreading of the wiki advice on Feature-Coupled Steps. Why not have "GIven a policy with a PCF practice state and seconday risk" Because the work we are currently doing is going to involve several hundred different variations of over a hundred different attributes of a policy. I need to make sure that I''m able to reuse as many statements describing that policy as I possibly can. Another factor is that our SME is going to be heavily involved in creating these scenarios. A few concessions toward regular English will help a great deal. This is not a featured coupled step because PCF practice state and secondary risk are part of the Policies state and are not seperate. Seperating the step as you have done does not reduce coupling. In fact all it does is complicate the steps because a variable containing the policy has to now be in the 3 steps. Perhaps the need for a with is a ''smell'' suggesting that you are seperating a step that is intrinsically coupled. So with really shouldn''t be needed at all. HTH Andrew 2009/3/13 Tim Hart <<mailto:THart at picagroup.com>THart at picagroup.com<mailto:THart at picagroup.com>> List, Quick question about Cucumber/Gherkin. I''m considering adding ''With'' as a step definition to support scenarios like: Given a policy With a PCF practice state And a secondary risk ... I''m fairly new to ruby - but I can''t quite get this one figured out. I''ve tried adding Cucumber.alias_steps ([''With'']) To my features/support/env.rb file, but when I run cucumber, I still get a Syntax error. It looks like my ''with'' never gets added to the original list. Suggestions? -- Tim Hart Senior Software Engineer PICA Group 615-713-9956 :cell timothyjhart :Y! <mailto:tjhart at me.com>tjhart at me.com<mailto:tjhart at me.com> :AIM ***************************************************************************** Disclaimer: This electronic message may contain information that is Confidential or legally privileged. It is intended only for the use of the individual(s) and entity named in the message. If you are not an intended recipient of this message, please notify the sender immediately and delete the material from your computer. Do not deliver, distribute or copy this message and do not disclose its contents or take any action in reliance on the information it contains. ***************************************************************************** _______________________________________________ rspec-users mailing list <mailto:rspec-users at rubyforge.org>rspec-users at rubyforge.org<mailto:rspec-users at rubyforge.org> <http://rubyforge.org/mailman/listinfo/rspec-users>http://rubyforge.org/mailman/listinfo/rspec-users _______________________________________________ rspec-users mailing list rspec-users at rubyforge.org<mailto:rspec-users at rubyforge.org> http://rubyforge.org/mailman/listinfo/rspec-users
On 14 Mar 2009, at 22:01, Tim Hart wrote:> On Mar 14, 2009, at 3:38 PM, "Andrew Premdas" <apremdas at gmail.com<mailto:apremdas at gmail.com > >> wrote: > > Is the syntax you''re using a misreading of the wiki advice on > Feature-Coupled Steps. > > Why not have > > "GIven a policy with a PCF practice state and seconday risk" > > Because the work we are currently doing is going to involve several > hundred different variations of over a hundred different attributes > of a policy. I need to make sure that I''m able to reuse as many > statements describing that policy as I possibly can.Have you thought about using Scenario Outlines to express these several hundred variations in a tabular format? That would enable you something like: Given a policy with <policy features> When blah Then <outcome> Examples: | policy features | outcome | | a PCF practice state and seconday risk | foo | Just a thought. Matt Wynne http://blog.mattwynne.net http://www.songkick.com
> That sounds like a great way to avoid the instance variable.Why is a named record preferable to an instance variable? It seems like the coupling between steps is the same, but the coupled state is stored differently. Maybe that''s the point - stored differently. I''ve been tempted to start scenario lines with "With" as well, to get away from the combinatorial explosion of setup steps for complex entities (think decorator pattern). I''ve used tables too, but mine looked more like this: Given a policy with: | PCF practice state | secondary risk | | yes | yes | Is that nasty? It means we can use one step to set all possible boolean attributes of a policy, but it doesn''t read so well. "With ..." would mean steps that were coupled to the "last mentioned thing". That seems like a different kind of coupling - there is only one piece of state involved (the last thing) rather than a map of named things. But it''s less explicit and implies that the "last thing" needs to be updated by each step that mentions things. Matt, going back to Mark''s example, it sounds like you lean towards the latter (i.e. repeat ''Reach from the Stars for ''Halo 3'' throughout the scenario). Is that correct? Josh On Sat, Mar 14, 2009 at 10:58 PM, Matt Wynne <matt at mattwynne.net> wrote:> > On 14 Mar 2009, at 22:01, Tim Hart wrote: > >> On Mar 14, 2009, at 3:38 PM, "Andrew Premdas" >> <apremdas at gmail.com<mailto:apremdas at gmail.com>> wrote: >> >> Is the syntax you''re using a misreading of the wiki advice on >> Feature-Coupled Steps. >> >> Why not have >> >> "GIven a policy with a PCF practice state and seconday risk" >> >> Because the work we are currently doing is going to involve several >> hundred different variations of over a hundred different attributes of a >> policy. I need to make sure that I''m able to reuse as many statements >> describing that policy as I possibly can. > > Have you thought about using Scenario Outlines to express these several > hundred variations in a tabular format? > > That would enable you something like: > > Given a policy with <policy features> > When blah > Then <outcome> > > Examples: > | policy features ? ? ? ? ? ? ? ? ? ? ? ?| outcome | > | a PCF practice state and seconday risk | foo ? ? | > > Just a thought. > > > > Matt Wynne > http://blog.mattwynne.net > http://www.songkick.com > > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users >
On 15 Mar 2009, at 00:30, Josh Chisholm wrote:>> That sounds like a great way to avoid the instance variable. > > Why is a named record preferable to an instance variable? It seems > like the coupling between steps is the same, but the coupled state is > stored differently. Maybe that''s the point - stored differently.I guess my view is that having the state out front in the scenario is preferable whenever possible (without cluttering up the feature with noise) because it''s clear, and there''s less risk of a gap opening up between what the step appears to do given its name, and what it actually does when it runs. I take this gap seriously because I put a great deal of trust our features.> I''ve been tempted to start scenario lines with "With" as well, to get > away from the combinatorial explosion of setup steps for complex > entities (think decorator pattern). I''ve used tables too, but mine > looked more like this: > > Given a policy with: > | PCF practice state | secondary risk | > | yes | yes | > > Is that nasty? It means we can use one step to set all possible > boolean attributes of a policy, but it doesn''t read so well.I don''t think that''s nasty, it seems entirely appropriate for that type of problem. It sounds like the type of acceptance tests I hear people like Keith Braithwaite talking about putting together for traders using Excel and Fit, and they seem to work really well. Thinking about this some more though, maybe there''s an argument for breaking the feature up into multiple features, and using Background to set up the common state of the objects, then have a few scenarios that build on this with different steps to tweak the objects. Just another idea - it''s really hard to judge without seeing more of the specific features.> "With ..." would mean steps that were coupled to the "last mentioned > thing". That seems like a different kind of coupling - there is only > one piece of state involved (the last thing) rather than a map of > named things. But it''s less explicit and implies that the "last thing" > needs to be updated by each step that mentions things.I know what you mean, and it would certainly make for nice readable scenarios. My worry is how maintainable the steps would be in the long run. I''m used to seeing steps like this: Given /the Policy has a secondary risk/ do Policy.count.should == 1 policy = Policy.first policy.secondary_risk = true policy.save end Which are pretty explicit and leave no room for accidental abuse. What the OP suggested would give you something more like this: Given /a Policy/ do @it = Factory(:policy) end With /a secondary risk/ do @it.secondary_risk = true @it.save end I dunno actually. Now I type it out it doesn''t seem so bad :)> Matt, going back to Mark''s example, it sounds like you lean towards > the latter (i.e. repeat ''Reach from the Stars for ''Halo 3'' throughout > the scenario). Is that correct?I guess my heuristic is something like this: 1. If I can simply refer to "the Widget" then I do, wherever possible. 2. If some attribute of the Widget is important in the scenario, I''ll explicitly set that attribute, and mention it again later in the assertions. e.g. Given a Widget named "Foo" When I delete the Widget Then I should see the text "bye bye Foo" 3. If I have to refer to multiple objects of the same class in one scenario, then I use names to differentiate between them. e.g. Given some Widgets named "Foo, Bar" When I delete the Widget "Foo" Then I should see 1 Widget And I should see the text "Bar" Matt Wynne http://blog.mattwynne.net http://www.songkick.com
I like that heuristic Matt. Actually coupling via the database is quite different to instance variables. The database state would exist if you followed through the scenario without cucumber e.g. manually. It occurred to me you could avoid the table like this too: Given a policy with a PCF practice state, secondary risk and something else Given /^a policy with (.+)$/ do | attributes | # create policy attributes.split(/(?:(?:,|\sand)\s)/).each do | attribute | # apply attributes "a PCF practice state", "secondary risk", "something else" end end Josh On Sun, Mar 15, 2009 at 1:18 AM, Matt Wynne <matt at mattwynne.net> wrote:> > On 15 Mar 2009, at 00:30, Josh Chisholm wrote: > >>> That sounds like a great way to avoid the instance variable. >> >> Why is a named record preferable to an instance variable? It seems >> like the coupling between steps is the same, but the coupled state is >> stored differently. Maybe that''s the point - stored differently. > > I guess my view is that having the state out front in the scenario is > preferable whenever possible (without cluttering up the feature with noise) > because it''s clear, and there''s less risk of a gap opening up between what > the step appears to do given its name, and what it actually does when it > runs. I take this gap seriously because I put a great deal of trust our > features. > >> I''ve been tempted to start scenario lines with "With" as well, to get >> away from the combinatorial explosion of setup steps for complex >> entities (think decorator pattern). I''ve used tables too, but mine >> looked more like this: >> >> Given a policy with: >> ?| PCF practice state | secondary risk | >> ?| yes ? ? ? ? ? ? ? ? ? ? ? ? | yes ? ? ? ? ? ? ? ? ? | >> >> Is that nasty? It means we can use one step to set all possible >> boolean attributes of a policy, but it doesn''t read so well. > > I don''t think that''s nasty, it seems entirely appropriate for that type of > problem. It sounds like the type of acceptance tests I hear people like > Keith Braithwaite talking about putting together for traders using Excel and > Fit, and they seem to work really well. > > Thinking about this some more though, maybe there''s an argument for breaking > the feature up into multiple features, and using Background to set up the > common state of the objects, then have a few scenarios that build on this > with different steps to tweak the objects. Just another idea - it''s really > hard to judge without seeing more of the specific features. > >> "With ..." would mean steps that were coupled to the "last mentioned >> thing". That seems like a different kind of coupling - there is only >> one piece of state involved (the last thing) rather than a map of >> named things. But it''s less explicit and implies that the "last thing" >> needs to be updated by each step that mentions things. > > I know what you mean, and it would certainly make for nice readable > scenarios. My worry is how maintainable the steps would be in the long run. > I''m used to seeing steps like this: > > Given /the Policy has a secondary risk/ do > ?Policy.count.should == 1 > ?policy = Policy.first > ?policy.secondary_risk = true > ?policy.save > end > > Which are pretty explicit and leave no room for accidental abuse. What the > OP suggested would give you something more like this: > > Given /a Policy/ do > ?@it = Factory(:policy) > end > > With /a secondary risk/ do > ?@it.secondary_risk = true > ?@it.save > end > > I dunno actually. Now I type it out it doesn''t seem so bad :) > > >> Matt, going back to Mark''s example, it sounds like you lean towards >> the latter (i.e. repeat ''Reach from the Stars for ''Halo 3'' throughout >> the scenario). Is that correct? > > I guess my heuristic is something like this: > > 1. If I can simply refer to "the Widget" then I do, wherever possible. > > 2. If some attribute of the Widget is important in the scenario, I''ll > explicitly set that attribute, and mention it again later in the assertions. > e.g. > ?Given a Widget named "Foo" > ?When I delete the Widget > ?Then I should see the text "bye bye Foo" > > 3. If I have to refer to multiple objects of the same class in one scenario, > then I use names to differentiate between them. e.g. > ?Given some Widgets named "Foo, Bar" > ?When I delete the Widget "Foo" > ?Then I should see 1 Widget > ?And I should see the text "Bar" > > > Matt Wynne > http://blog.mattwynne.net > http://www.songkick.com > > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users >
> I know what you mean, and it would certainly make for nice readable > scenarios. My worry is how maintainable the steps would be in the long > run. I''m used to seeing steps like this: > > Given /the Policy has a secondary risk/ do > Policy.count.should == 1 > policy = Policy.first > policy.secondary_risk = true > policy.save > end > > Which are pretty explicit and leave no room for accidental abuse. What > the OP suggested would give you something more like this: > > Given /a Policy/ do > @it = Factory(:policy) > end > > With /a secondary risk/ do > @it.secondary_risk = true > @it.save > end > > I dunno actually. Now I type it out it doesn''t seem so bad :) >As previously mentioned in the thread another way to phrase this is with step tables. Here is the code I use: http://gist.github.com/59007 (related blog post: http://www.benmabey.com/2009/02/05/leveraging-test-data-builders-in-cucumber-steps/) I have been using instance variables in my steps (but naming them after the model, i.e. @policy) but Matt''s DB solution is nice in some respects. Both ways fall apart when you have multiple polices, but in that case you should probably be passing in the name or some other identifying aspect of the model. Anyways, it seems like a pattern is emerging on how to carry state to other steps when you have to. I was bored so I combined both approaches: module ObjectLocators def the_policy if @policy @policy else case Policy.count when 0 raise "There is no @policy variable defined and no policy in the DB! Establish state in previous step or create a new policy." when 1 Policy.first else raise "There are multiple policies in DB and no @policy variable set! Please disambiguate the state in previous step." end end end end World { |world| world.extend(ObjectLocators) } (this code is here: http://gist.github.com/79470) Like I said, I was bored and haven''t really tried this. I don''t know if I even like it, but I thought extracting out the patterns would be useful. You could leverage factories just as I do in my previous gist to provide locator (locater?) for all of your models. Great thread BTW. -Ben
On 15 Mar 2009, at 16:52, Ben Mabey wrote:> >> I know what you mean, and it would certainly make for nice readable >> scenarios. My worry is how maintainable the steps would be in the >> long run. I''m used to seeing steps like this: >> >> Given /the Policy has a secondary risk/ do >> Policy.count.should == 1 >> policy = Policy.first >> policy.secondary_risk = true >> policy.save >> end >> >> Which are pretty explicit and leave no room for accidental abuse. >> What the OP suggested would give you something more like this: >> >> Given /a Policy/ do >> @it = Factory(:policy) >> end >> >> With /a secondary risk/ do >> @it.secondary_risk = true >> @it.save >> end >> >> I dunno actually. Now I type it out it doesn''t seem so bad :) >> > > As previously mentioned in the thread another way to phrase this is > with step tables. Here is the code I use: > > http://gist.github.com/59007 (related blog post: http://www.benmabey.com/2009/02/05/leveraging-test-data-builders-in-cucumber-steps/) > > I have been using instance variables in my steps (but naming them > after the model, i.e. @policy) but Matt''s DB solution is nice in > some respects. Both ways fall apart when you have multiple polices, > but in that case you should probably be passing in the name or some > other identifying aspect of the model. Anyways, it seems like a > pattern is emerging on how to carry state to other steps when you > have to. I was bored so I combined both approaches: > > module ObjectLocators > > def the_policy > if @policy > @policy > else > case Policy.count > when 0 > raise "There is no @policy variable defined and no policy in > the DB! Establish state in previous step or create a new policy." > when 1 > Policy.first > else > raise "There are multiple policies in DB and no @policy > variable set! Please disambiguate the state in previous step." > end > end > end > > end > > > World { |world| world.extend(ObjectLocators) } > > (this code is here: http://gist.github.com/79470) > > Like I said, I was bored and haven''t really tried this. I don''t > know if I even like it, but I thought extracting out the patterns > would be useful. You could leverage factories just as I do in my > previous gist to provide locator (locater?) for all of your models.We have some very similar code deep in the bowels of Songkick''s features folder that is a little scrappy, but does help us solve this problem quite nicely. Basically there''s a regular expression that matches on phrases of the following form: the Widget the Widget "Foo" "Foo" So you can use that in your step matchers like this: When /I delete (#{THE_THING})/ |identifier| thing_to_delete = identified_model(identifier) end If you want to remember something just by the "Foo" label, you have to throw it into a collection, imaginatively named ''stuff'', as you do so: stuff["Foo"] = Factory(:widget, :name => "Foo") As I say it''s a little scrappy as it''s something we threw together ages ago and haven''t really felt the need to revisit, but hopefully it will give someone some ideas: http://gist.github.com/79496 Matt Wynne http://blog.mattwynne.net http://www.songkick.com
It''s SRP applied to cucumber steps - just do it - keep your steps small and composable Sent from my iPhone On Mar 14, 2009, at 9:18 PM, Matt Wynne <matt at mattwynne.net> wrote:> > On 15 Mar 2009, at 00:30, Josh Chisholm wrote: > >>> That sounds like a great way to avoid the instance variable. >> >> Why is a named record preferable to an instance variable? It seems >> like the coupling between steps is the same, but the coupled state is >> stored differently. Maybe that''s the point - stored differently. > > I guess my view is that having the state out front in the scenario > is preferable whenever possible (without cluttering up the feature > with noise) because it''s clear, and there''s less risk of a gap > opening up between what the step appears to do given its name, and > what it actually does when it runs. I take this gap seriously > because I put a great deal of trust our features. > >> I''ve been tempted to start scenario lines with "With" as well, to get >> away from the combinatorial explosion of setup steps for complex >> entities (think decorator pattern). I''ve used tables too, but mine >> looked more like this: >> >> Given a policy with: >> | PCF practice state | secondary risk | >> | yes | yes | >> >> Is that nasty? It means we can use one step to set all possible >> boolean attributes of a policy, but it doesn''t read so well. > > I don''t think that''s nasty, it seems entirely appropriate for that > type of problem. It sounds like the type of acceptance tests I hear > people like Keith Braithwaite talking about putting together for > traders using Excel and Fit, and they seem to work really well. > > Thinking about this some more though, maybe there''s an argument for > breaking the feature up into multiple features, and using Background > to set up the common state of the objects, then have a few scenarios > that build on this with different steps to tweak the objects. Just > another idea - it''s really hard to judge without seeing more of the > specific features. > >> "With ..." would mean steps that were coupled to the "last mentioned >> thing". That seems like a different kind of coupling - there is only >> one piece of state involved (the last thing) rather than a map of >> named things. But it''s less explicit and implies that the "last >> thing" >> needs to be updated by each step that mentions things. > > I know what you mean, and it would certainly make for nice readable > scenarios. My worry is how maintainable the steps would be in the > long run. I''m used to seeing steps like this: > > Given /the Policy has a secondary risk/ do > Policy.count.should == 1 > policy = Policy.first > policy.secondary_risk = true > policy.save > end > > Which are pretty explicit and leave no room for accidental abuse. > What the OP suggested would give you something more like this: > > Given /a Policy/ do > @it = Factory(:policy) > end > > With /a secondary risk/ do > @it.secondary_risk = true > @it.save > end > > I dunno actually. Now I type it out it doesn''t seem so bad :) > > >> Matt, going back to Mark''s example, it sounds like you lean towards >> the latter (i.e. repeat ''Reach from the Stars for ''Halo 3'' throughout >> the scenario). Is that correct? > > I guess my heuristic is something like this: > > 1. If I can simply refer to "the Widget" then I do, wherever possible. > > 2. If some attribute of the Widget is important in the scenario, > I''ll explicitly set that attribute, and mention it again later in > the assertions. e.g. > Given a Widget named "Foo" > When I delete the Widget > Then I should see the text "bye bye Foo" > > 3. If I have to refer to multiple objects of the same class in one > scenario, then I use names to differentiate between them. e.g. > Given some Widgets named "Foo, Bar" > When I delete the Widget "Foo" > Then I should see 1 Widget > And I should see the text "Bar" > > > Matt Wynne > http://blog.mattwynne.net > http://www.songkick.com > > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users