Monday, March 23, 2009

Proper Cucumber Sinatra Driving

‹prev | My Chain | next›

During my Cucumber / Sinatra spike, I ended up driving the development / test / production database URLs with a method defined right in the main body of the Sinatra app:
#####
# Use a different CouchDB instance in test mode
def db
Sinatra::Application.environment == :test ?
"http://localhost:5984/eee-test" :
"http://localhost:5984/eee-meals"
end
While reading through the Sinatra documentation, I came across the configure :environment method, which seems to be the Sinatra idiomatic way to do this. So I add the following to the empty eee.rb file from yesterday:
require 'rubygems'
require 'sinatra'
require 'rest_client'
require 'json'

configure :test do
@@db = "http://localhost:5984/eee-test"
end

configure :development, :production do
@@db = "http://localhost:5984/eee"
end
Following along with the spike, I add the following to features/support/env.rb:
Before do
RestClient.put @@db, { }
end

After do
RestClient.delete @@db
end
Running cucumber features/recipe_details.feature, however, gives this:
Feature: Recipe Details  # features/recipe_details.feature

So that I can accurately reproduce a recipe at home
As a web user
I want to be able to easily recognize important details
Scenario: Viewing a recipe with several ingredients # features/recipe_details.feature:7
/home/cstrom/.gem/ruby/1.8/gems/rest-client-0.9.2/lib/restclient/request.rb:144:in `process_result': HTTP status code 412 (RestClient::RequestFailed)
from /home/cstrom/.gem/ruby/1.8/gems/rest-client-0.9.2/lib/restclient/request.rb:106:in `transmit'
from /usr/lib/ruby/1.8/net/http.rb:543:in `start'
from /home/cstrom/.gem/ruby/1.8/gems/rest-client-0.9.2/lib/restclient/request.rb:103:in `transmit'
from /home/cstrom/.gem/ruby/1.8/gems/rest-client-0.9.2/lib/restclient/request.rb:36:in `execute_inner'
from /home/cstrom/.gem/ruby/1.8/gems/rest-client-0.9.2/lib/restclient/request.rb:28:in `execute'
from /home/cstrom/.gem/ruby/1.8/gems/rest-client-0.9.2/lib/restclient/request.rb:12:in `execute'
from /home/cstrom/.gem/ruby/1.8/gems/rest-client-0.9.2/lib/restclient.rb:65:in `put'
from ./features/support/env.rb:22:in `__cucumber_-610192688'
...
If RestClient is failing, it is time to check couch.log, which shows:
[info] [<0.2824.0>] 127.0.0.1 - - 'PUT' /eee 412
Hunh? PUTing /eee? But that is the development DB (which already exists, hence the 412). So what's up?

It turns out the configure blocks are evaluated during the require at the beginning of features/support/env.rb. Adding ENV['RACK_ENV'] = 'test' to the top of that file:
ENV['RACK_ENV'] = 'test'

# NOTE: This must come before the require 'webrat', otherwise
# sinatra will look in the wrong place for its views.
require File.dirname(__FILE__) + '/../../eee'
resolves the issue:
cstrom@jaynestown:~/repos/eee-code$ cucumber features/recipe_details.feature -n
Feature: Recipe Details

So that I can accurately reproduce a recipe at home
As a web user
I want to be able to easily recognize important details
Scenario: Viewing a recipe with several ingredients
Given a recipe for Buttermilk Chocolate Chip Pancakes
When I view the recipe
Then I should see an ingredient of "1 cup of all-purpose, unbleached flour"
And I should see an ingredient of "¼ teaspoons salt"
And I should see an ingredient of "chocolate chips (Nestle Tollhouse)"

Scenario: Viewing a recipe with non-active prep time
Given a recipe for Crockpot Lentil Andouille Soup
When I view the recipe
Then I should see 15 minutes of prep time
And I should see that it requires 5 hours of non-active cook time

Scenario: Viewing a list of tools used to prepare the recipe
Given a recipe for Chicken Noodle Soup
When I view the recipe
Then I should see that it requires a bowl, a colander, a cutting board, a pot and a skimmer to prepare

Scenario: Main site categories
Given a recipe for Mango and Tomato Salad
And site-wide categories of Italian, Asian, Latin, Breakfast, Chicken, Fish, Meat, Salad, and Vegetarian
When I view the recipe
Then the Salad and Vegetarian categories should be active


4 scenarios
16 steps pending (16 with no step definition)

You can use these snippets to implement pending steps which have no step definition:
...
I am not certain that is much better than original inline method, but I will stick with idiomatic Sinatra wherever possible.

Time to get started on implementing those steps...

No comments:

Post a Comment