Friday, March 6, 2009

Finishing the Cucumber and Sinatra Spike

‹prev | My Chain | next›

I got the Cucumber with Sinatra spike underway last night. I could not quite seal the deal when I ran into some problems with Cucumber step definitions.

Recall that this was the output of cucumber -n features:
cstrom@jaynestown:~/repos/eee-code$ cucumber features -n
Feature: See a meal

So that I can see an old meal
As a web user
I want to browse a single meal by permalink
Scenario: View Meal
Given a "Breakfast Elves" meal
When I view the meal permalink
Then the title should include "Breakfast Elves"


1 scenario
3 steps pending (3 with no step definition)

You can use these snippets to implement pending steps which have no step definition:

Given /^a "Breakfast Elves" meal$/ do
end

When /^I view the meal permalink$/ do
end

Then /^the title should include "Breakfast Elves"$/ do
end
Those very simple steps can be implemented in features/step_definitions/browse_meals.rb as:
Given /^a "Breakfast Elves" meal$/ do
end

When /^I view the meal permalink$/ do
visit("/meals/2005-12-07-breakfast-elves")
end

Then /^the title should include "Breakfast Elves"$/ do
response.body.should have_selector("h1", :content => "Breakfast Elves")
end
The Given step needs no implementation because it is being run against the CouchDB instance from two nights ago. That raises the question of how to deal with tearing down test data with Sinatra. For now, my guess is that it needs to be done manually—a side-effect of working so close to the metal. I will defer the real answer for another day.

Right now, I simply want to ensure that Cucumber is properly interacting with Sinatra. So, I run cucumber -n features and get the following:
Feature: See a meal

So that I can see an old meal
As a web user
I want to browse a single meal by permalink
Scenario: View Meal
Given a "Breakfast Elves" meal
When I view the meal permalink
Then the title should include "Breakfast Elves"
undefined method `has_selector?' for # (NoMethodError)
./features/step_definitions/browse_meals.rb:9:in `Then /^the title should include "Breakfast Elves"$/'
features/browse_meals.feature:11:in `Then the title should include "Breakfast Elves"'


1 scenario
2 steps passed
1 step failed
Hunh, missing "has_selector?" method? Isn't that just part of Cucumber?

Turns out that, at least for the version of Cucumber and Webrat that I installed last night (0.1.16 and 0.4.2), the Webrat::SinatraSession instance needs to be extended with Webrat::Matchers. This may have been fixed in a more recent versions of Cucumber, which would explain why the sinatraCucumber / Sinatra documentation does not include it.

At any rate, the cucumber features/support/env.rb file is updated to extend the Webrat::SinatraSession thusly:
# NOTE: This must come before the require 'webrat', otherwise
# sinatra will look in the wrong place for it's views.
require File.dirname(__FILE__) + '/../../spike'

# RSpec matchers
require 'spec/expectations'

# Webrat
require 'webrat'
Webrat.configure do |config|
config.mode = :sinatra
end

World do
session = Webrat::SinatraSession.new
session.extend(Webrat::Matchers)
session
end
Then re-running the Cucumber features, we get:
cstrom@jaynestown:~/repos/eee-code$ cucumber features -n
Feature: See a meal

So that I can see an old meal
As a web user
I want to browse a single meal by permalink
Scenario: View Meal
Given a "Breakfast Elves" meal
When I view the meal permalink
Then the title should include "Breakfast Elves"


1 scenario
3 steps passed

Next Steps

As mentioned above, I have no answer for how to prevent previous step definitions from potentially impacting later steps (or even subsequent features). I need to answer that before I am done with this spike.

Another question occurred to me about whether to put meals and recipes into the same couch DB database or to put them into two separate DBs. Right now, my thinking is to put them into the same database and to rely on CouchDB views to pick out the right type.

2 comments:

  1. Cucumber provides a Before and After hook which will help clean-up the db in-between each Scenario.

    http://wiki.github.com/aslakhellesoy/cucumber/hooks


    Leaving your Given without anything in some what confused me. I've never used coachDB before. Do you have a reliance that the db state is already setup? I would generally say in order to avoid state coupling I would want to ensure that I was in control of the environment setup for a scenario.

    Otherwise one change in the db could break all your tests.

    ReplyDelete
  2. Joseph, thanks for the link. That's exactly what I was looking for and didn't even have to go to the trouble of looking :)

    The blank Given is definitely a no-no in real tests. I'm only spiking here trying to figure out the ins and outs of Cucumber with Sinatra. I'm gonna delete everything once I think I have a handle on it (and, thanks to you, I'm pretty close now!).

    But, yeah, that blank Given is relying on pre-existing data that I created in:

    http://japhr.blogspot.com/2009/03/spike-sinatra-and-couchdb.html

    I'll see what I can do about removing that dependency tonight...

    ReplyDelete