1. Installed rvm (Ruby Version Manager). See Episode 200. Rails3 Beta and RVM
rupert:tsa rupert$ rvm ruby-1.9.2-p0
rupert:tsa rupert$ ruby -v
ruby 1.9.2p0 (2010-08-18 revision 29036) [x86_64-darwin10.5.0]

To use ruby-1.9.2-p0 as default

rupert:rails3 rupert$ rvm ruby-1.9.2-p0 --default
rupert:rails3 rupert$ ruby -v
ruby 1.9.2p0 (2010-08-18 revision 29036) [x86_64-darwin10.5.0]
  1. Install rails3
gem install rails
  1. Create a rails app tsa (the sample app)
rails new tsa -d mysql
  1. Start webrick. Yup, script/server is gone
rupert:tsa rupert$ rails server -e development
=> Booting WEBrick
=> Rails 3.0.3 application starting in production on http://0.0.0.0:3000
=> Call with -d to detach
=> Ctrl-C to shutdown server
[2010-12-06 20:47:27] INFO  WEBrick 1.3.1
[2010-12-06 20:47:27] INFO  ruby 1.9.2 (2010-08-18) [x86_64-darwin10.5.0]
[2010-12-06 20:47:27] INFO  WEBrick::HTTPServer#start: pid=1348 port=3000

Note: Upon checking http://127.0.0.1:3000/ I get a “Routing Error”

  1. Update your GemFile with the necessary gems.
    Let’s use devise as a login authentication system.
source 'http://rubygems.org'
 
gem 'rails', '3.0.3'
 
# Bundle edge Rails instead:
# gem 'rails', :git => 'git://github.com/rails/rails.git'
 
gem 'mysql2'
gem 'devise', :git => "git://github.com/plataformatec/devise.git", :branch => "master"

Then run bundle install. This will install devise gem.

rupert:tsa rupert$ bundle install
Fetching git://github.com/plataformatec/devise.git
remote: Counting objects: 10326, done.
remote: Compressing objects: 100% (3745/3745), done.
remote: Total 10326 (delta 6603), reused 9755 (delta 6163)
Receiving objects: 100% (10326/10326), 1.24 MiB | 314 KiB/s, done.
Resolving deltas: 100% (6603/6603), done.
Fetching source index for http://rubygems.org/

Where are the gems installed?

rupert:tsa rupert$ bundle show devise
/Users/rupert/.rvm/gems/ruby-1.9.2-p0/bundler/gems/devise-b50fd1a72e71
  1. Create the necessary databases in mysql. See config/database.yml
CREATE DATABASE tsa_development;
  1. Run devise generator.
rupert:tsa rupert$ rails generate devise:install
      create  config/initializers/devise.rb
      create  config/locales/devise.en.yml
 
===============================================================================
 
Some setup you must do manually if you havent yet:
 
  1. Setup default url options for your specific environment. Here is an
     example of development environment:
 
       config.action_mailer.default_url_options = { :host => 'localhost:3000' }
 
     This is a required Rails configuration. In production it must be the
     actual host of your application
 
  2. Ensure you have defined root_url to *something* in your config/routes.rb.
     For example:
 
       root :to => "home#index"
 
  3. Ensure you have flash messages in app/views/layouts/application.html.erb.
     For example:
 
       <p class="notice"><%= notice %></p>
       <p class="alert"><%= alert %></p>
 
===============================================================================
  1. Generate a controller in Rails3.
rupert:tsa rupert$ rails generate controller main index
      create  app/controllers/main_controller.rb
       route  get "main/index"
      invoke  erb
      create    app/views/main
      create    app/views/main/index.html.erb
      invoke  test_unit
      create    test/functional/main_controller_test.rb
      invoke  helper
      create    app/helpers/main_helper.rb
      invoke    test_unit
      create      test/unit/helpers/main_helper_test.rb

Update routes.rb for the root_url

  root :to => "main#index"
  1. Create a User model with devise.
rupert:tsa rupert$ rails generate devise User
      invoke  active_record
      create    app/models/user.rb
      invoke    test_unit
      create      test/unit/user_test.rb
      create      test/fixtures/users.yml
      create    db/migrate/20101206104321_devise_create_users.rb
      insert    app/models/user.rb
       route  devise_for :users
rupert:tsa rupert$
  1. Run migration for User model
rupert:tsa rupert$ export RAILS_ENV=development
rupert:tsa rupert$ rake db:migrate
(in /Users/rupert/projects/rails3/tsa)
==  DeviseCreateUsers: migrating ==============================================
-- create_table(:users)
   -> 0.0805s
-- add_index(:users, :email, {:unique=>true})
   -> 0.1368s
-- add_index(:users, :reset_password_token, {:unique=>true})
   -> 0.1484s
==  DeviseCreateUsers: migrated (0.3662s) =====================================
  1. Using cucumber
sudo port install libxml2 libxslt
  1. Update Gemfile
group :test, :development do
  gem 'rspec'
  gem 'rspec-rails'
  gem 'cucumber'
  gem 'cucumber-rails'
  gem 'capybara'
  gem 'launchy'
end
  1. Rspec
rupert:tsa rupert$ rails g rspec:install
      create  .rspec
      create  spec
      create  spec/spec_helper.rb
      create  autotest
      create  autotest/discover.rb
  1. Cucumber
rupert:tsa rupert$ rails g cucumber:install --rspec --capybara
      create  config/cucumber.yml
      create  script/cucumber
       chmod  script/cucumber
      create  features/step_definitions
      create  features/step_definitions/web_steps.rb
      create  features/support
      create  features/support/paths.rb
      create  features/support/env.rb
       exist  lib/tasks
      create  lib/tasks/cucumber.rake
        gsub  config/database.yml
        gsub  config/database.yml
       force  config/database.yml
  1. Write your first feature
Feature: Home Page
  In order to make sure the home page works
  As a normal user
  I want to see the home page
 
Scenario: Show Main Sections
  When I go to the home page
  Then show me the page
  Then I should see "Login"

From Harold Jimenez:

*“The Given step is where you set up the context of your scenario. Every scenario starts with a blank slate, so it is important to create a state in your application for example by creating data in the database, or by navigating to a specific page. </p> The When step is where you exercise the application in order to accomplish what needs testing. In the case of a web app like twiddr, this is usually where you fill in forms, press buttons, click links, or otherwise interact with the system in some way.

Finally, the Then step is where you verify the result, and it’s where we check that the correct pages are rendered, that we see a success or error message, or anything that could help us verify that the prior action was successful. As we move along with creating our own features, this will become much clearer.”</em></blockquote>

  1. See it fail in cucumber
rake features  (or)
cucumber (or)
bundle exec cucumber features/home.feature
rupert:tsa rupert$ cucumber
Using the default profile...
F--
 
(::) failed steps (::)
 
Can't find mapping from "the home page" to a path.
Now, go and add a mapping in /Users/rupert/projects/rails3/tsa/tsa/features/support/paths.rb (RuntimeError)
./features/support/paths.rb:26:in `rescue in path_to'
./features/support/paths.rb:20:in `path_to'
./features/step_definitions/web_steps.rb:24:in `/^(?:|I )go to (.+)$/'
features/home.feature:7:in `When I go to the home page'
 
Failing Scenarios:
cucumber features/home.feature:6 # Scenario: Show Main Sections
 
1 scenario (1 failed)
3 steps (1 failed, 2 skipped)
0m0.062s
  1. Defining “the home page” in the support/paths.rb
    when /the home page/
      root_path

and in the routes.rb

root :to => "home#index"

Other examples:

when /the profile page for "([^\"]+)"/
  user = User.find_by_twiddr_name!($1)
  user_path(user)

Note: When you see the error

undefined local variable or method `node' for #<Capybara::Driver::RackTest::Node:0x00000101151ad8> (NameError)"

You need to comment in features/support/env.rb

#require 'cucumber/rails/capybara_javascript_emulation'

For more info, read https://rspec.lighthouseapp.com/projects/16211-cucumber/tickets/674

  1. Then show me the page will open up the browser
file://localhost/Users/rupert/projects/rails3/tsa/tsa/tmp/capybara/capybara-20101209222149.html
  1. Automatic Testing with “autotest”. When you save a file, autotest automatically runs cucumber. To avoid autotest infinite loop with cucumber, make sure your IDE (i.e rubymine) does not save automatically in the file system. You can exclude files and directories from autotest with a “.autotest” file
Autotest.add_hook :initialize do |at|
  at.add_exception(%r{^\./\.git})
  at.add_exception(%r{^\./db})
  at.add_exception(%r{^\./log})
  at.add_exception(%r{^\./tmp})
  at.add_exception(%r{^\./.idea})
  at.add_exception(%r{^\./rerun\.txt})
  at.add_exception(%r{^\./Gemfile\.lock})
end

Now you can run, autotest from the terminal. Save a file and see autotest run.

autotest
  1. If you have javascript AJAX calls included in cucumber scenarios, you need to append them with @javascript tag. Below is a sample which selects “Australia” from the “Country” and waits for the ajax request to finish before selecting the “State” drop down. More info on capybara github.
@javascript
Scenario: Creating a Fleet
  And I select "Australia" from "Country"
  And I wait for the ajax request to finish
  And I select "Victoria" from "State"

How does the step “I wait for the ajax request to finish” looks like? http://stackoverflow.com/questions/7286254/cucumber-wait-for-ajaxsuccess

When /^I wait for the ajax request to finish$/ do
  start_time = Time.now
  page.evaluate_script('jQuery.isReady&&jQuery.active==0').class.should_not eql(String) until page.evaluate_script('jQuery.isReady&&jQuery.active==0') or (start_time + 5.seconds) < Time.now
    sleep 1
  end
end