Thanks to Greg Sterndale for running the show and Plectix for footing the food bill, we had a fantastic hands-on workshop last evening on Cucumber. The turnout was much better than expected – I think nearly 20 people attended!

Greg did a great job taking us through the Cucumber basics – walking through an example demonstrating pending and unimplemented features. Here are some take-aways and interesting conversation points.
We attempted to use modern tools and techniques for this project. The workshop project, called Code Stache, uses Rails 2.3.5 and the soon-to-be-de-facto gem bundler for gem specifying and inventorying (um, but it doesn’t work in ruby1.9). Gem bundler is fairly new, so it was not surprising that there was some discussion on this topic. The folks who use gem bundler seem to agree it is awesome but there are some missing features, including more usage instructions and visibility to what is actually going on during the bundle process.
After rake bundle, we were good to go. One important aspect (and feature) of gem bundler is any “binaries” that gems create (like cucumber or rspec) will end up in RAILS_ROOT/bin. These should be used instead of the system gems to ensure the correct version is being executed. So from RAILS_ROOT, instead of issuing:
cucumber
You should run:
bin/cucumber
Fairly quickly our of the gate, we had a discussion on using object factories instead of fixtures. Examples of object factories include factory_girl and Machinist - both work really well with Cucumber. In our example, we used factory_girl.
Some of the Machinist fans found the integration of Sham and Faker for completely random data, along with simple association declarations makes it a solid choice. It was also brought up that factory_girl could use the Machinist API (at least I think this was mentioned).
But without getting into a religious war, using an object factory pattern is clearly a win.
The discussion of what the actual value of human-readable features is and if it’s worth the effort go through this DSL. Some developers out there believe it is not worth the effort, but the consensus at the workshop was cucumber human-readable features are worth it. It also seemed that developers are primarily responsible for authoring feature files; then QA or stakeholders review and provide acceptance.
Along with non-programmer interaction with feature files, the use of instance variables is a common topic when discussing cucumber. Using instance vars does make individual steps less modular – you can’t cherry-pick a step if it relies on something being set, for one. But setting up a state, like an actor or current user, can simplify features with intentional and calculated deviation from pure “no-ivar” philosophy.
In the end, it seemed that being pragmatic and trying to minimize the use of instance variables was the consensus.
Pickle is a nice way to interact with your object factories in cucumber. Steve created a pickle branch in codestache where the manual factory step was replaced with Pickle steps.
features/share_code.feature
@@ -17,6 +17,6 @@ Scenario: Create a code snippet
And I should be on the "sudo rm -rf /" snippet page
Scenario: View a code snippet
- Given a snippet exists with a body of "sudo rm -rf /"
+ Given a snippet exists with body: "sudo rm -rf /"
features/step_definitions/share_code_steps.rb
@@ -1,3 +0,0 @@
-Given /^a snippet exists with an? (.*) of "([^"]*)"$/ do |attr, value|
- Factory(:snippet, attr.gsub(' ', '_') => value)
-end
Later today in IRC (#boston.rb), Dan Pickett pointed out that factory_girl actually has some undocumented pickle-like step definitions.
In the original codestache title branch, we had a feature like this to help us specify there ought to be two fields, body and title, using some webrat CSS selectors:
Scenario: Visit the home page
Given I am on the home page
Then I should see "New snippet"
And I should see "Title" within "label[for=snippet_title]"
And I should see "Body" within "label[for=snippet_body]"
Arguably, this exposes internal view implementation and not business requirements. Fortunately, ajvargo was in attendance and provided this step definition that uses XPath to marry up semantic form labels to their respective fields. It is still work-in-progress, and won’t work with the non-for, <label>Label<input id="foo" name="foo"/></label> style, but removes the CSS selector from the feature (and I believe he also mentioned this works well with Selenium).
# Uses xpath to check for a form element based on the label,
# instead of using a css selector.
Then /^I should see a "([^\"]*)" for "([^\"]*)"$/ do |type, name|
case type
when 'Button'
response.should have_xpath("//input[@type='submit' and @value='#{name}']")
when 'Text Field'
response.should have_xpath("//input[@type='text' and @id=..//label[normalize-space(text())=\"#{name}\"]//@for]")
when 'Text Area'
response.should have_xpath("//textarea[@id=..//label[normalize-space(text())=\"#{name}\"]//@for]")
when 'Radio Button'
pending
when 'Select Field'
response.should have_xpath("//select[@id=..//label[normalize-space(text())=\"#{name}\"]//@for]")
else pending
end
end
So with this step definition, our feature could now like this:
Scenario: Visit the home page
Given I am on the home page
Then I should see "New snippet"
And I should see a "Text Field" for "Title"
And I should see a "Text Area" for "Body"
One area we didn’t get to much into was the reuse of scenarios in step definitions. For instance, some login feature could be cuke’d with ample of detail, then consolidated and referenced as a ‘When I successfully login’ step for subsequent new features.
Another item we missed talking about was cucumber tagging. As cucumber test suites can grow in size and run-time, using tagging can be a way to isolate tests locally during development (continuous integration should continue to run the entire suite). Also, we didn’t really cover the special @wip tag, which marks features as works-in-progress.
Other feedback included better instructions getting people setup before-hand. Our internet pipe was laboring as everyone was cloning the project at the same time.
The balance of roughly 50% discussion and 50% hands-on coding, seems to resonate well.
All-in-all, it was a very successful maiden “Newer Yankee Workshop” – we are looking forward (and looking for topic suggestions) for future ones!
Cucumber: http://cukes.info
Webrat: http://wiki.github.com/brynary/webrat
Background on BDD and user stories: http://dannorth.net/whats-in-a-story http://www.infoq.com/news/2008/06/new-user-story-format http://sirenian.livejournal.com/47679.html
Handy XPath step definition: http://gist.github.com/257503
Gemcutter: http://gemcutter.org
Gem Bundler: http://github.com/wycats/bundler http://yehudakatz.com/2009/11/03/using-the-new-gem-bundler-today/
factory_girl: http://github.com/thoughtbot/factory_girl
Machinist: http://github.com/notahat/machinist
Rubular, helpful for crafting regular expressions: http://rubular.com
Pickle: http://ianwhite.github.com/pickle/
Railscasts (Cucumber, Webrat and Pickle): http://railscasts.com/episodes?search=cucumber
Getting setup (with link to a great Cucumber/TextMate bundle): http://neweryankee.github.com/codestache/
Greg’s simple slides from last night: http://www.slideshare.net/gsterndale/cucumber-2730469
And of course, Code Stache http://codestache.com/snippets/1