Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Fixed rspec2/rails3 integration; added integration tests for macros/m…

…atchers/rspec in rails 2 and 3 using cucumber
  • Loading branch information...
commit cb7eae11b548456daf3d6746e3fd73c38318a2c9 1 parent a559fc8
@jferris jferris authored
View
1  .gitignore
@@ -6,3 +6,4 @@ pkg
*.swp
*.swo
tags
+tmp
View
39 Rakefile
@@ -1,10 +1,12 @@
+require 'rubygems'
require 'rake'
require 'rake/testtask'
require 'rake/rdoctask'
require 'rake/gempackagetask'
+require 'cucumber/rake/task'
$LOAD_PATH.unshift("lib")
-require 'shoulda'
+require 'shoulda/version'
load 'tasks/shoulda.rake'
# Test::Unit::UI::VERBOSE
@@ -30,13 +32,6 @@ task :coverage do
system "rcov --rails --sort coverage -Ilib #{files.join(' ')}"
end
-desc 'Default: run tests for all supported versions of Rails'
-task :default do
- %w(2.3.8 3.0.0.beta4).each do |version|
- system("RAILS_VERSION=#{version} rake -s test;")
- end
-end
-
eval("$specification = begin; #{IO.read('shoulda.gemspec')}; end")
Rake::GemPackageTask.new $specification do |pkg|
pkg.need_tar = true
@@ -45,3 +40,31 @@ end
desc "Clean files generated by rake tasks"
task :clobber => [:clobber_rdoc, :clobber_package]
+
+namespace :cucumber do
+ Cucumber::Rake::Task.new(:rails2, "Run the cucumber features in Rails 2") do |t|
+ t.fork = true
+ t.cucumber_opts = ['--format', (ENV['CUCUMBER_FORMAT'] || 'progress')]
+ t.profile = 'rails2'
+ end
+
+ Cucumber::Rake::Task.new(:rails3, "Run the cucumber features in Rails 3") do |t|
+ t.fork = true
+ t.cucumber_opts = ['--format', (ENV['CUCUMBER_FORMAT'] || 'progress')]
+ t.profile = 'rails3'
+ end
+end
+
+desc "Run the cucumber features in both Rails 2 and 3"
+task :cucumber => ["cucumber:rails2", "cucumber:rails3"]
+
+desc 'run tests for all supported versions of Rails'
+task :test_all do
+ %w(2.3.8 3.0.0.beta4).each do |version|
+ system("RAILS_VERSION=#{version} rake -s test;")
+ end
+end
+
+desc 'Default: run test and cucumber features for support versions'
+task :default => [:test_all, :cucumber]
+
View
2  cucumber.yml
@@ -0,0 +1,2 @@
+rails2: -r features/support -r features/step_definitions/common_steps.rb -r features/step_definitions/rails2_steps.rb
+rails3: -r features/support -r features/step_definitions/common_steps.rb -r features/step_definitions/rails3_steps.rb
View
115 features/rails_integration.feature
@@ -0,0 +1,115 @@
+Feature: integrate with Rails
+
+ Background:
+ When I generate a new rails application
+ And I configure the application to use "shoulda" from this project
+ And I save the following as "db/migrate/1_create_users.rb"
+ """
+ class CreateUsers < ActiveRecord::Migration
+ def self.up
+ create_table :users do |t|
+ t.string :name
+ end
+ end
+ end
+ """
+ When I run "rake db:migrate"
+ And I save the following as "app/models/user.rb"
+ """
+ class User < ActiveRecord::Base
+ validates_presence_of :name
+ end
+ """
+ When I save the following as "app/controllers/examples_controller.rb"
+ """
+ class ExamplesController < ApplicationController
+ def show
+ @example = 'hello'
+ render :nothing => true
+ end
+ end
+ """
+ When I configure a wildcard route
+
+ Scenario: generate a rails application and use macros in Test::Unit
+ When I save the following as "test/unit/user_test.rb"
+ """
+ require 'test_helper'
+
+ class UserTest < ActiveSupport::TestCase
+ should_validate_presence_of :name
+ end
+ """
+ When I save the following as "test/functional/examples_controller_test.rb"
+ """
+ require 'test_helper'
+
+ class ExamplesControllerTest < ActionController::TestCase
+ def setup
+ get :show
+ end
+
+ should_respond_with :success
+ should_assign_to :example
+ end
+ """
+ When I run "rake test TESTOPTS=-v"
+ Then I should see "1 tests, 1 assertions, 0 failures, 0 errors"
+ And I should see "2 tests, 2 assertions, 0 failures, 0 errors"
+ And I should see "User should require name to be set"
+ And I should see "ExamplesController should assign @example"
+
+ Scenario: generate a rails application and use matchers in Test::Unit
+ When I save the following as "test/unit/user_test.rb"
+ """
+ require 'test_helper'
+
+ class UserTest < ActiveSupport::TestCase
+ should validate_presence_of(:name)
+ end
+ """
+ When I save the following as "test/functional/examples_controller_test.rb"
+ """
+ require 'test_helper'
+
+ class ExamplesControllerTest < ActionController::TestCase
+ def setup
+ get :show
+ end
+
+ should respond_with(:success)
+ should assign_to(:example)
+ end
+ """
+ When I run "rake test TESTOPTS=-v"
+ Then I should see "1 tests, 1 assertions, 0 failures, 0 errors"
+ And I should see "2 tests, 2 assertions, 0 failures, 0 errors"
+ And I should see "User should require name to be set"
+ And I should see "ExamplesController should assign @example"
+
+ Scenario: generate a rails application and use matchers in Rspec
+ When I configure the application to use rspec-rails
+ And I run the rspec generator
+ And I save the following as "spec/models/user_spec.rb"
+ """
+ require 'spec_helper'
+
+ describe User do
+ it { should validate_presence_of(:name) }
+ end
+ """
+ When I save the following as "spec/controllers/examples_controller_spec.rb"
+ """
+ require 'spec_helper'
+
+ describe ExamplesController, "show" do
+ before { get :show }
+ # rspec2 doesn't use the controller as the subject
+ subject { controller }
+ it { should assign_to(:example) }
+ end
+ """
+ When I run "rake spec SPEC_OPTS=-fs"
+ Then I should see "2 examples, 0 failures"
+ And I should see "should require name to be set"
+ And I should see "should assign @example"
View
31 features/step_definitions/common_steps.rb
@@ -0,0 +1,31 @@
+PROJECT_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..', '..')).freeze
+TEMP_ROOT = File.join(PROJECT_ROOT, 'tmp').freeze
+APP_NAME = 'testapp'.freeze
+RAILS_ROOT = File.join(TEMP_ROOT, APP_NAME).freeze
+
+Before do
+ FileUtils.rm_rf(TEMP_ROOT)
+ FileUtils.mkdir_p(TEMP_ROOT)
+ @terminal = Terminal.new
+end
+
+After do
+ FileUtils.rm_f(File.join(PROJECT_ROOT, '.specification'))
+end
+
+When /^I save the following as "([^\"]*)"$/ do |path, string|
+ FileUtils.mkdir_p(File.join(RAILS_ROOT, File.dirname(path)))
+ File.open(File.join(RAILS_ROOT, path), 'w') { |file| file.write(string) }
+end
+
+When /^I run "([^\"]*)"$/ do |command|
+ @terminal.cd(RAILS_ROOT)
+ @terminal.run(command)
+end
+
+Then /^I should see "([^\"]*)"$/ do |expected_text|
+ unless @terminal.output.include?(expected_text)
+ raise("Got terminal output:\n#{@terminal.output}\n\nExpected output:\n#{expected_text}")
+ end
+end
+
View
83 features/step_definitions/rails2_steps.rb
@@ -0,0 +1,83 @@
+When /^I generate a new rails application$/ do
+ load_rails = <<-RUBY
+ gem 'rails', '2.3.8'; \
+ load Gem.bin_path('rails', 'rails', '2.3.8')
+ RUBY
+
+ @terminal.cd(TEMP_ROOT)
+ @terminal.run(%{ruby -rubygems -e "#{load_rails.strip!}" #{APP_NAME}})
+end
+
+When /^I configure the application to use "([^\"]+)" from this project$/ do |name|
+ gemspec = File.join(PROJECT_ROOT, "#{name}.gemspec")
+ eval("$specification = begin; #{IO.read(gemspec)}; end")
+ version = $specification.version
+ name = $specification.name
+
+ vendor_gem_root = File.join(RAILS_ROOT, 'vendor', 'gems')
+ vendor_gem_path = File.join(vendor_gem_root, "shoulda-#{version}")
+
+ FileUtils.mkdir_p(vendor_gem_root)
+ FileUtils.ln_s(PROJECT_ROOT, vendor_gem_path)
+ File.open(File.join(vendor_gem_path, ".specification"), "w") do |file|
+ file.write($specification.to_yaml)
+ end
+
+ insert_into_environment("config.gem '#{name}'")
+end
+
+When /^I configure the application to use rspec\-rails$/ do
+ # we have to unpack and copy the generator because Rails won't find the
+ # generators if rspec-rails 2 is installed
+ insert_into_environment("config.gem 'rspec-rails', :lib => false, :version => '1.2.9'")
+ insert_into_environment("config.gem 'rspec', :lib => false, :version => '1.2.9'")
+ steps %{
+ When I run "rake gems:unpack"
+ }
+ rspec_generator = File.join(RAILS_ROOT,
+ 'vendor',
+ 'gems',
+ 'rspec-rails-1.2.9',
+ 'generators')
+ FileUtils.cp_r(rspec_generator, File.join(RAILS_ROOT, 'lib'))
+end
+
+When /^I run the rspec generator$/ do
+ steps %{
+ When I run the "rspec" generator
+ }
+end
+
+When /^I run the "([^"]*)" generator$/ do |name|
+ steps %{
+ When I run "./script/generate #{name}"
+ }
+end
+
+When /^I configure a wildcard route$/ do
+ steps %{
+ When I save the following as "config/routes.rb"
+ """
+ ActionController::Routing::Routes.draw do |map|
+ map.connect ':controller/:action/:id'
+ end
+ """
+ }
+end
+
+module InsertionHelpers
+ def insert_into(path, find, replace)
+ contents = IO.read(path)
+ contents.sub!(find, replace)
+ File.open(path, "w") { |file| file.write(contents) }
+ end
+
+ def insert_into_environment(contents)
+ environment_file = File.join(RAILS_ROOT, 'config', 'environment.rb')
+ initializer = "Rails::Initializer.run do |config|"
+ replace = "#{initializer}\n #{contents}"
+ insert_into(environment_file, initializer, replace)
+ end
+end
+
+World(InsertionHelpers)
View
60 features/step_definitions/rails3_steps.rb
@@ -0,0 +1,60 @@
+When /^I generate a new rails application$/ do
+ @terminal.cd(TEMP_ROOT)
+ @terminal.run("rails _3.0.0.beta4_ new #{APP_NAME}")
+ steps %{
+ When I save the following as "Gemfile"
+ """
+ source "http://rubygems.org"
+ gem 'rails', '3.0.0.beta4'
+ gem 'sqlite3-ruby', :require => 'sqlite3'
+ """
+ }
+end
+
+When /^I configure the application to use "([^\"]+)" from this project$/ do |name|
+ append_to_gemfile "gem '#{name}', :path => '../../'"
+ steps %{And I run "bundle lock"}
+end
+
+When /^I run the "([^"]*)" generator$/ do |name|
+ steps %{
+ When I run "./script/rails generate #{name}"
+ }
+end
+
+When /^I run the rspec generator$/ do
+ steps %{
+ When I run the "rspec:install" generator
+ }
+end
+
+When /^I configure the application to use rspec\-rails$/ do
+ append_to_gemfile "gem 'rspec-rails', '>= 2.0.0.beta.12'"
+ steps %{And I run "bundle lock"}
+end
+
+When /^I configure a wildcard route$/ do
+ steps %{
+ When I save the following as "config/routes.rb"
+ """
+ Rails.application.routes.draw do |map|
+ match ':controller(/:action(/:id(.:format)))'
+ end
+ """
+ }
+end
+
+module AppendHelpers
+ def append_to(path, contents)
+ File.open(path, "a") do |file|
+ file.puts
+ file.puts contents
+ end
+ end
+
+ def append_to_gemfile(contents)
+ append_to(File.join(RAILS_ROOT, 'Gemfile'), contents)
+ end
+end
+
+World(AppendHelpers)
View
36 features/support/terminal.rb
@@ -0,0 +1,36 @@
+require 'fileutils'
+
+class Terminal
+ attr_reader :output, :status
+
+ def initialize
+ @cwd = FileUtils.pwd
+ @output = ""
+ @status = 0
+ @logger = Logger.new(File.join(TEMP_ROOT, 'terminal.log'))
+ end
+
+ def cd(directory)
+ @cwd = directory
+ end
+
+ def run(command)
+ output << "#{command}\n"
+ FileUtils.cd(@cwd) do
+ logger.debug(command)
+ result = `#{command} 2>&1`
+ logger.debug(result)
+ output << result
+ end
+ @status = $?
+ end
+
+ def echo(string)
+ logger.debug(string)
+ end
+
+ private
+
+ attr_reader :logger
+end
+
View
8 lib/shoulda.rb
@@ -1,7 +1,9 @@
require 'shoulda/version'
-if defined? Spec
- require 'shoulda/rspec'
+if defined?(RSpec)
+ require 'shoulda/integrations/rspec2'
+elsif defined?(Spec)
+ require 'shoulda/integrations/rspec'
else
- require 'shoulda/test_unit'
+ require 'shoulda/integrations/test_unit'
end
View
0  lib/shoulda/rspec.rb → lib/shoulda/integrations/rspec.rb
File renamed without changes
View
22 lib/shoulda/integrations/rspec2.rb
@@ -0,0 +1,22 @@
+require 'shoulda/active_record/matchers'
+require 'shoulda/action_controller/matchers'
+require 'shoulda/action_mailer/matchers'
+
+# :enddoc:
+
+module RSpec
+ module Matchers
+ include Shoulda::ActiveRecord::Matchers
+ end
+
+ module Rails
+ module ControllerExampleGroup
+ include Shoulda::ActionController::Matchers
+ end
+
+ module MailerExampleGroup
+ include Shoulda::ActionMailer::Matchers
+ end
+ end
+end
+
View
0  lib/shoulda/test_unit.rb → lib/shoulda/integrations/test_unit.rb
File renamed without changes
View
4 rails/init.rb
@@ -1,8 +1,8 @@
if RAILS_ENV == 'test'
if defined? Spec
- require 'shoulda/rspec'
+ require 'shoulda/integrations/rspec'
else
- require 'shoulda/rails'
+ require 'shoulda/integrations/test_unit'
Shoulda.autoload_macros RAILS_ROOT, File.join("vendor", "{plugins,gems}", "*")
end
end
Please sign in to comment.
Something went wrong with that request. Please try again.