Hi, I just posted a tiny app that I put together for a presentation on Cucumber. http://github.com/thoughtless/cuc_demo/tree/master This essentially mirrors the workflow that I strive towards. (The README explains more.) I don''t want to put myself out there as the standard to immitate, but I think it will be helpful for people just getting started with TDD/Cucumber/RSpec. I''d really appreciate your feedback! Paul P.S. Sorry to the guys on IRC who got this message twice. -- Posted via http://www.ruby-forum.com/.
Fernando García Samblas
2008-Dec-01 19:00 UTC
[rspec-users] Sample App - TDD with Cucumber and RSpec
Paul, thanks for sharing your examples. I was just thinking about posting something that can be introduced nicely with your sample app. Now in cuc_demo we''ve got a step definition for /^there are no posties$/ in postie_steps.rb. This way, if we''d need to add a "Given there are no users" step we should create a user_steps.rb with a similar definition. IMHO it would be nice to have instead a "context_definitions.rb" with common "givens" (similar to navigation_definitions.rb) and there a more general definition, like for instance: Given /^there are no (.*)$/ do |thing| thing_to_model(thing).destroy_all end In our World we should have a thing_to_class method with the mappings between the names used in features and the model class that implement them. I think this mapping is also useful if tomorrow you and/or your client decides to call it "pasties" instead of "posties" (and is more than useful if you''re writing your features in other language than English, cause you cannot obtain the class name through transformations of the original "thing"). Cheers, nando Pau Cor escribi?:> Hi, > > I just posted a tiny app that I put together for a presentation on > Cucumber. > http://github.com/thoughtless/cuc_demo/tree/master > > This essentially mirrors the workflow that I strive towards. (The README > explains more.) I don''t want to put myself out there as the standard to > immitate, but I think it will be helpful for people just getting started > with TDD/Cucumber/RSpec. > > I''d really appreciate your feedback! > > Paul > > P.S. Sorry to the guys on IRC who got this message twice. >-- Fernando Garc?a Samblas fernando.garcia at the-cocktail.com The Cocktail C/ Salamanca 17 28020 Madrid +34 91 567 06 05
On 1 Dec 2008, at 19:00, Fernando Garc?a Samblas wrote:> > Paul, > > thanks for sharing your examples. I was just thinking about posting > something that can be introduced nicely with your sample app. > > Now in cuc_demo we''ve got a step definition for /^there are no > posties$/ > in postie_steps.rb. This way, if we''d need to add a "Given there are > no > users" step we should create a user_steps.rb with a similar > definition. > > IMHO it would be nice to have instead a "context_definitions.rb" with > common "givens" (similar to navigation_definitions.rb) and there a > more > general definition, like for instance: > > Given /^there are no (.*)$/ do |thing| > thing_to_model(thing).destroy_all > end > > In our World we should have a thing_to_class method with the mappings > between the names used in features and the model class that > implement them. > > I think this mapping is also useful if tomorrow you and/or your client > decides to call it "pasties" instead of "posties" (and is more than > useful if you''re writing your features in other language than English, > cause you cannot obtain the class name through transformations of the > original "thing").We have a convention here at Songkick (after a great deal of debate) that it''s OK to refer to key domain concepts like Concerts, Artists, Venues etc by their Ruby class name from within the scenario. Thus our thing_to_model function is always a matter of just calling thing.constantize. I greatly prefer this to having any kind of custom mapping - it promotes the ''ubiquitous language'' that Eric Evans talks about in the original DDD book. Maybe it''s different when you''re working in another language though - I guess it''s preferable to use English names for classes etc, is it? Matt Wynne http://blog.mattwynne.net http://www.songkick.com
Fernando Garc?a Samblas wrote:> IMHO it would be nice to have instead a "context_definitions.rb" with > common "givens" (similar to navigation_definitions.rb) and there a more > general definition, like for instance:...> Given /^there are no (.*)$/ do |thing|I really like that. It will make it much more clear since "Given there are no" will be a very common step. Paul -- Posted via http://www.ruby-forum.com/.
On 2 Dec 2008, at 08:04, Pau Cor wrote:>> Given /^there are no (.*)$/ do |thing| > > I really like that. It will make it much more clear since "Given there > are no" will be a very common step.Hmmm, I personally think it''s safer to set up each scenario from a blank slate. I''ve used "Given there are no X" steps before, but they are just stubs to make the scenario read right, ie they simply don''t create anything, rather than destroying existing data. The current implementation, Given /^there are no posties$/ do Postie.destroy_all end strikes me more of a when step, eg When /^all posties are destroyed$/ do Postie.destroy_all end A Before block to destroy the Posties (and any other models) will probably reduce issues in the long run if Postie began to depend on another object, and was trapped by a database constraint. Ashley -- http://www.patchspace.co.uk/ http://aviewfromafar.net/
Fernando García Samblas
2008-Dec-02 14:22 UTC
[rspec-users] Sample App - TDD with Cucumber and RSpec
Matt Wynne escribi?:> Maybe it''s different when you''re working in another language though - > I guess it''s preferable to use English names for classes etc, is it?Exactly Matt that''s it. I forgot to explain that, thanks for mention it. We use pure English in our code and Spanish in the features. A business term in Spanish can have a bunch of possible translations to English. The mapping functions let us now exactly what are we talking about, reducing ambiguity and improving communication with business people.> > 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 >-- Fernando Garc?a Samblas fernando.garcia at the-cocktail.com http://nando.lacoctelera.com The Cocktail C/ Salamanca 17 28020 Madrid +34 91 567 06 05
Ashley Moran <ashley.moran at patchspace.co.uk> writes:> On 2 Dec 2008, at 08:04, Pau Cor wrote: > >>> Given /^there are no (.*)$/ do |thing| >> >> I really like that. It will make it much more clear since "Given there >> are no" will be a very common step. > > Hmmm, I personally think it''s safer to set up each scenario from a > blank slate. I''ve used "Given there are no X" steps before, but they > are just stubs to make the scenario read right, ie they simply don''t > create anything, rather than destroying existing data. > > The current implementation, > Given /^there are no posties$/ do > Postie.destroy_all > end > > strikes me more of a when step, eg > When /^all posties are destroyed$/ do > Postie.destroy_all > end > > A Before block to destroy the Posties (and any other models) will > probably reduce issues in the long run if Postie began to depend on > another object, and was trapped by a database constraint. > > AshleyI''m with you on this. In fact, I think my implementation would be Given ... Postie.count.should == 0 end It''s just an assertion (in the C sense of the word, not testing). You should be starting off with a clean slate anyway...but having a couple assertions before you run can be very helpful for localization. Plus this step can obviously be reused as a When. Pat
Fernando García Samblas
2008-Dec-02 21:16 UTC
[rspec-users] Sample App - TDD with Cucumber and RSpec
Ashley Moran escribi?:> > On 2 Dec 2008, at 08:04, Pau Cor wrote: > >>> Given /^there are no (.*)$/ do |thing| >> >> I really like that. It will make it much more clear since "Given there >> are no" will be a very common step. > > Hmmm, I personally think it''s safer to set up each scenario from a > blank slate. I''ve used "Given there are no X" steps before, but they > are just stubs to make the scenario read right, ie they simply don''t > create anything, rather than destroying existing data.Yes, I also agree with you and Pat. Givens should create the scenario context, not clean the garbage left by others. But I was using it just as an example of "reusing" common Givens (after all it was the only Given in Paul''s example app), the same way we do with Whens a Thens. Take this example instead: Given /^there is (?:a|an) (.*)$/ do |thing| @resources ||= [] @resources << thing_to_model(thing).create end Using a model factory like FixturesReplacement you can deal with required data. WDYT?> > The current implementation, > Given /^there are no posties$/ do > Postie.destroy_all > end > > strikes me more of a when step, eg > When /^all posties are destroyed$/ do > Postie.destroy_all > end > > A Before block to destroy the Posties (and any other models) will > probably reduce issues in the long run if Postie began to depend on > another object, and was trapped by a database constraint. > > Ashley >-- Fernando Garc?a Samblas fernando.garcia at the-cocktail.com http://nando.lacoctelera.com The Cocktail C/ Salamanca 17 28020 Madrid +34 91 567 06 05
On 2 Dec 2008, at 19:25, Pat Maddox wrote:> Given ... > Postie.count.should == 0 > end > > It''s just an assertion (in the C sense of the word, not testing). You > should be starting off with a clean slate anyway...but having a couple > assertions before you run can be very helpful for localization. Plus > this step can obviously be reused as a When.Nice idea! That kind of sanity checking can''t hurt. Ashley -- http://www.patchspace.co.uk/ http://aviewfromafar.net/