Sunday, October 19, 2008

Cucumber scenarios need a title

So I'm playing with Behavior Driven Development (BDD) and Ruby on Rails using Cucumber and Webrat. I thought I'd start with the simplest feature I could think of, "I want to see the application name in the title". So, off we go with features/site_layout.feature:
Feature: Site Layout
  In order to build familiarity
  As a user
  I want to see the application name in the title

  Scenario:
    Given I am on the home page
    Then the title tag should be "WOW App"
I create features/steps/site_steps.rb:
Given /^I am on (.*)$/ do |page|
  visits case page
         when "the home page"
           "/"
         else
           raise "Can't find mapping from \"#{page}\" to a path"
         end
end

Then /^the (.*) tag should be "(.*)"$/ do |tag, content|
  response.should have_tag(tag, content)
end
And run it with "rake features". What I get is:
C:\dev\temp>rake features
(in C:/dev/temp)
Feature: Site Layout  # features/site_layout.feature
  In order to build familiarity
  As a user
  I want to see the application name in the title
  Scenario: Given I am on the home page     # features/site_layout.feature:6
    Then the title tag should be "WOW App"  # features/steps/site_steps.rb:10
      You have a nil object when you didn't expect it!
      The error occurred while evaluating nil.content_type (NoMethodError)
      ...
      ./features/steps/site_steps.rb:11:in `Then /^the (.*) tag should be "(.*)"$/'
      features/site_layout.feature:8:in `Then the title tag should be "WOW App"'


1 steps failed
rake aborted!
Not quite what I had in mind, I was expecting a failure, but got an error. Nevermind, this is all very new to me, so I'll push on and it'll all become clear right? I create an app/views/layouts/application.html.erb:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
       "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
  <head>
  <meta http-equiv="content-type" content="text/html;charset=UTF-8" />
    <title>WOW App</title>
  </head>
  <body>
  </body>
</html>
Run the feature again ... no joy, same error. Hours of web searching leads me nowhere. Finally while looking at some examples I noticed that my Scenario doesn't have a description, so I add one on line 6:
Feature: Site Layout
  In order to build familiarity
  As a user
  I want to see the application name in the title

  Scenario: On the home page
    Given I am on the home page
    Then the title tag should be "WOW App"
Now I get:
C:\dev\temp>rake features
(in C:/dev/temp)
Feature: Site Layout  # features/site_layout.feature
  In order to build familiarity
  As a user
  I want to see the application name in the title
  Scenario: On the home page                # features/site_layout.feature:6
    Given I am on the home page             # features/steps/site_steps.rb:1
      No route matches "/" with {:method=>:get} (ActionController::RoutingError)
...
      features/site_layout.feature:7:in `Given I am on the home page'
    Then the title tag should be "WOW App"  # features/steps/site_steps.rb:10


1 steps failed
1 steps skipped
rake aborted!
A quick addition to config/routes.rb:
map.root :controller => 'example'
And a stub controller from "ruby script\generate controller Example index", I get:
C:\dev\temp>rake features
(in C:/dev/temp)
Feature: Site Layout  # features/site_layout.feature
  In order to build familiarity
  As a user
  I want to see the application name in the title
  Scenario: On the home page                # features/site_layout.feature:6
    Given I am on the home page             # features/steps/site_steps.rb:1
    Then the title tag should be "WOW App"  # features/steps/site_steps.rb:10


2 steps passed
Hurrah!

Sunday, October 5, 2008

Where to put sqlite3.dll on Windows

When I first started using SQLite3 on Windows, most people suggested downloading sqlite3.dll from www.sqlite.org and storing it in ruby/bin so Windows could find it. For a while, this strategy worked fine but I really didn't like the application requiring users to put that DLL into an acceptable place. I don't know why it didn't occur to me earlier, but, given that this is only intended to be a Windows application, why not just modify the PATH environment variable within the application. So that's what I've done. In config/boot.rb:
# Make sqlite3.dll available
ENV['PATH'] += ";#{RAILS_ROOT}/vendor/bin/sqlite3"

Thursday, October 2, 2008

class << self

I've come across this construct many times while browsing a number of open source projects:
class MyClass
  class << self
    def a_class_method
      ...
    end
  end

  def an_instance_method
    ...
  end
end
I finally got it today ... there's no black magic ... all "class << self" means is:
add the following class method definitions to the class MyClass.
Or,
open the class MyClass, and add the following class methods.
Now that I'm in the gang and understand this incantation, I'm not sure I like it. It seems like a nice way to group all your class methods together, but if you define several class methods then it becomes harder to recognize whether a method belongs to the class or an instance. I think it's cleaner to explicitly state the ownership of each method:
class MyClass
  def self.a_class_method
    ...
  end

  def an_instance_method
    ...
  end
end