From 51aaa412cc99137ae0b7b0198bfae82fd4cff171 Mon Sep 17 00:00:00 2001 From: Dalibor Nasevic Date: Fri, 6 Jan 2012 16:15:26 +0100 Subject: [PATCH] Setup testing strategy --- .rspec | 1 + Gemfile | 8 ++ Gemfile.lock | 15 +++ Guardfile | 36 ++++++ config/application.rb | 2 +- config/environments/test.rb | 2 +- features/step_definitions/app_steps.rb | 2 +- features/support/env.rb | 119 ++++++++++-------- script/cucumber | 10 -- script/test | 36 ++++++ .../admin/attachments_controller_spec.rb | 1 - spec/factories/editor.rb | 2 +- spec/models/editor_spec.rb | 2 +- spec/rcov.opts | 2 - spec/spec.opts | 4 - spec/spec_helper.rb | 98 +++++++-------- spec/support/helpers.rb | 13 ++ spec/support/shared_examples.rb | 12 ++ 18 files changed, 234 insertions(+), 131 deletions(-) create mode 100644 Guardfile delete mode 100755 script/cucumber create mode 100755 script/test delete mode 100644 spec/rcov.opts delete mode 100644 spec/spec.opts create mode 100644 spec/support/helpers.rb create mode 100644 spec/support/shared_examples.rb diff --git a/.rspec b/.rspec index 53607ea..61f260b 100644 --- a/.rspec +++ b/.rspec @@ -1 +1,2 @@ --colour +--drb diff --git a/Gemfile b/Gemfile index 6373633..86fded1 100644 --- a/Gemfile +++ b/Gemfile @@ -34,6 +34,13 @@ group :development do gem 'haml-rails' # haml generators gem 'ruby-debug' gem 'mongrel' + + gem 'guard' + # gem 'guard-cucumber' + # gem 'guard-rspec' + gem 'guard-spork' + gem 'libnotify' + gem 'rb-inotify' end group :development, :test do @@ -51,4 +58,5 @@ group :test do gem 'shoulda-matchers' gem 'email_spec' gem 'launchy' + gem 'spork', '~> 0.9.0.rc' end diff --git a/Gemfile.lock b/Gemfile.lock index adfaa19..28d09f3 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -88,6 +88,12 @@ GEM gem_plugin (0.2.3) gherkin (2.7.2) json (>= 1.4.6) + guard (0.10.0) + ffi (>= 0.5.0) + thor (~> 0.14.6) + guard-spork (0.5.0) + guard (>= 0.10.0) + spork (>= 0.8.4) haml (3.1.4) haml-rails (0.3.4) actionpack (~> 3.0) @@ -109,6 +115,7 @@ GEM json (1.6.4) launchy (2.0.5) addressable (~> 2.2.6) + libnotify (0.7.1) libv8 (3.3.10.4) linecache (0.46) rbx-require-relative (> 0.0.4) @@ -160,6 +167,8 @@ GEM rdoc (~> 3.4) thor (~> 0.14.6) rake (0.9.2.2) + rb-inotify (0.8.8) + ffi (>= 0.5.0) rbx-require-relative (0.0.5) rdoc (3.12) json (~> 1.4) @@ -198,6 +207,7 @@ GEM rubyzip sexp_processor (3.0.10) shoulda-matchers (1.0.0) + spork (0.9.0.rc9) sprockets (2.0.3) hike (~> 1.2) rack (~> 1.0) @@ -234,6 +244,8 @@ DEPENDENCIES database_cleaner email_spec factory_girl_rails + guard + guard-spork haml haml-rails honeypot-captcha @@ -241,17 +253,20 @@ DEPENDENCIES inherited_resources jquery-rails launchy + libnotify modernizr-rails mongrel mysql2 (>= 0.3) paperclip pickle rails (= 3.1.3) + rb-inotify rspec-rails (>= 2.8.0) ruby-debug ruby_parser sass-rails (~> 3.1.4) shoulda-matchers + spork (~> 0.9.0.rc) therubyracer uglifier (>= 1.0.3) web-app-theme (>= 0.6.2) diff --git a/Guardfile b/Guardfile new file mode 100644 index 0000000..6c2f153 --- /dev/null +++ b/Guardfile @@ -0,0 +1,36 @@ +# A sample Guardfile +# More info at https://github.com/guard/guard#readme + +guard 'spork', :cucumber_env => { 'RAILS_ENV' => 'test' }, :rspec_env => { 'RAILS_ENV' => 'test' } do + watch('config/application.rb') + watch('config/environment.rb') + watch(%r{^config/environments/.+\.rb$}) + watch(%r{^config/initializers/.+\.rb$}) + watch('Gemfile') + watch('Gemfile.lock') + watch('spec/spec_helper.rb') { :rspec } + watch('test/test_helper.rb') { :test_unit } + watch(%r{features/support/}) { :cucumber } +end + +# guard 'cucumber', :cli => "--drb", :all_after_pass => false, :all_on_start => false do +# watch(%r{^features/.+\.feature$}) +# watch(%r{^features/support/.+$}) { 'features' } +# watch(%r{^features/step_definitions/(.+)_steps\.rb$}) { |m| Dir[File.join("**/#{m[1]}.feature")][0] || 'features' } +# end + +# guard 'rspec', :cli => "--drb", :all_after_pass => false, :all_on_start => false, :version => 2 do +# watch(%r{^spec/.+_spec\.rb$}) +# watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" } +# watch('spec/spec_helper.rb') { "spec" } + +# # Rails example +# watch(%r{^app/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" } +# watch(%r{^app/(.*)(\.erb|\.haml)$}) { |m| "spec/#{m[1]}#{m[2]}_spec.rb" } +# watch(%r{^app/controllers/(.+)_(controller)\.rb$}) { |m| ["spec/routing/#{m[1]}_routing_spec.rb", "spec/#{m[2]}s/#{m[1]}_#{m[2]}_spec.rb", "spec/acceptance/#{m[1]}_spec.rb"] } +# watch(%r{^spec/support/(.+)\.rb$}) { "spec" } +# watch('config/routes.rb') { "spec/routing" } +# watch('app/controllers/application_controller.rb') { "spec/controllers" } +# # Capybara request specs +# watch(%r{^app/views/(.+)/.*\.(erb|haml)$}) { |m| "spec/requests/#{m[1]}_spec.rb" } +# end diff --git a/config/application.rb b/config/application.rb index 961ab80..de4edec 100644 --- a/config/application.rb +++ b/config/application.rb @@ -73,7 +73,7 @@ class Application < Rails::Application end Time::DATE_FORMATS[:date] = "%B %d, %Y" -Time::DATE_FORMATS[:post] = "%d %B, %Y %H:%m" +Time::DATE_FORMATS[:post] = "%d %B, %Y %H:%M" # load settings APP_CONFIG = YAML.load_file("#{Rails.root}/config/config.yml")[Rails.env] diff --git a/config/environments/test.rb b/config/environments/test.rb index a443c89..f705edb 100644 --- a/config/environments/test.rb +++ b/config/environments/test.rb @@ -12,7 +12,7 @@ config.static_cache_control = "public, max-age=3600" # Log error messages when you accidentally call methods on nil - config.whiny_nils = true + config.whiny_nils = false # Show full error reports and disable caching config.consider_all_requests_local = true diff --git a/features/step_definitions/app_steps.rb b/features/step_definitions/app_steps.rb index 76c12cd..41812bc 100644 --- a/features/step_definitions/app_steps.rb +++ b/features/step_definitions/app_steps.rb @@ -15,7 +15,7 @@ end Given /^I am logged in as admin$/ do - Factory.create(:editor, :is_admin => true) + Factory.create(:editor, :is_admin => true, :email => "pink.panter@gmail.com") steps %Q{ Given I am logged in as "pink.panter@gmail.com" } diff --git a/features/support/env.rb b/features/support/env.rb index 02de570..3cb9606 100644 --- a/features/support/env.rb +++ b/features/support/env.rb @@ -1,55 +1,68 @@ -# IMPORTANT: This file is generated by cucumber-rails - edit at your own peril. -# It is recommended to regenerate this file in the future when you upgrade to a -# newer version of cucumber-rails. Consider adding your own code to a new file -# instead of editing this one. Cucumber will automatically load all features/**/*.rb -# files. - -require 'cucumber/rails' - -# Capybara defaults to XPath selectors rather than Webrat's default of CSS3. In -# order to ease the transition to Capybara we set the default here. If you'd -# prefer to use XPath just remove this line and adjust any selectors in your -# steps to use the XPath syntax. -Capybara.default_selector = :css - -# By default, any exception happening in your Rails application will bubble up -# to Cucumber so that your scenario will fail. This is a different from how -# your application behaves in the production environment, where an error page will -# be rendered instead. -# -# Sometimes we want to override this default behaviour and allow Rails to rescue -# exceptions and display an error page (just like when the app is running in production). -# Typical scenarios where you want to do this is when you test your error pages. -# There are two ways to allow Rails to rescue exceptions: -# -# 1) Tag your scenario (or feature) with @allow-rescue -# -# 2) Set the value below to true. Beware that doing this globally is not -# recommended as it will mask a lot of errors for you! -# -ActionController::Base.allow_rescue = false - -# Remove/comment out the lines below if your app doesn't have a database. -# For some databases (like MongoDB and CouchDB) you may need to use :truncation instead. -begin - DatabaseCleaner.strategy = :transaction -rescue NameError - raise "You need to add database_cleaner to your Gemfile (in the :test group) if you wish to use it." +require 'rubygems' +require 'spork' + +Spork.prefork do + # IMPORTANT: This file is generated by cucumber-rails - edit at your own peril. + # It is recommended to regenerate this file in the future when you upgrade to a + # newer version of cucumber-rails. Consider adding your own code to a new file + # instead of editing this one. Cucumber will automatically load all features/**/*.rb + # files. + + require 'cucumber/rails' + + # Capybara defaults to XPath selectors rather than Webrat's default of CSS3. In + # order to ease the transition to Capybara we set the default here. If you'd + # prefer to use XPath just remove this line and adjust any selectors in your + # steps to use the XPath syntax. + Capybara.default_selector = :css + + # By default, any exception happening in your Rails application will bubble up + # to Cucumber so that your scenario will fail. This is a different from how + # your application behaves in the production environment, where an error page will + # be rendered instead. + # + # Sometimes we want to override this default behaviour and allow Rails to rescue + # exceptions and display an error page (just like when the app is running in production). + # Typical scenarios where you want to do this is when you test your error pages. + # There are two ways to allow Rails to rescue exceptions: + # + # 1) Tag your scenario (or feature) with @allow-rescue + # + # 2) Set the value below to true. Beware that doing this globally is not + # recommended as it will mask a lot of errors for you! + # + ActionController::Base.allow_rescue = false + + # Remove/comment out the lines below if your app doesn't have a database. + # For some databases (like MongoDB and CouchDB) you may need to use :truncation instead. + begin + DatabaseCleaner.strategy = :transaction + rescue NameError + raise "You need to add database_cleaner to your Gemfile (in the :test group) if you wish to use it." + end + + # You may also want to configure DatabaseCleaner to use different strategies for certain features and scenarios. + # See the DatabaseCleaner documentation for details. Example: + # + # Before('@no-txn,@selenium,@culerity,@celerity,@javascript') do + # DatabaseCleaner.strategy = :truncation, {:except => %w[widgets]} + # end + # + # Before('~@no-txn', '~@selenium', '~@culerity', '~@celerity', '~@javascript') do + # DatabaseCleaner.strategy = :transaction + # end + # + + # Possible values are :truncation and :transaction + # The :transaction strategy is faster, but might give you threading problems. + # See https://github.com/cucumber/cucumber-rails/blob/master/features/choose_javascript_database_strategy.feature + Cucumber::Rails::Database.javascript_strategy = :truncation end -# You may also want to configure DatabaseCleaner to use different strategies for certain features and scenarios. -# See the DatabaseCleaner documentation for details. Example: -# -# Before('@no-txn,@selenium,@culerity,@celerity,@javascript') do -# DatabaseCleaner.strategy = :truncation, {:except => %w[widgets]} -# end -# -# Before('~@no-txn', '~@selenium', '~@culerity', '~@celerity', '~@javascript') do -# DatabaseCleaner.strategy = :transaction -# end -# - -# Possible values are :truncation and :transaction -# The :transaction strategy is faster, but might give you threading problems. -# See https://github.com/cucumber/cucumber-rails/blob/master/features/choose_javascript_database_strategy.feature -Cucumber::Rails::Database.javascript_strategy = :truncation +Spork.each_run do + # # This code will be run each time you run your specs. + # require 'cucumber/rails/world' + # Cucumber::Rails.use_transactional_fixtures + # Cucumber::Rails.bypass_rescue # Comment out this line if you want Rails own error handling + # # (e.g. rescue_action_in_public / rescue_responses / rescue_from) +end diff --git a/script/cucumber b/script/cucumber deleted file mode 100755 index 7fa5c92..0000000 --- a/script/cucumber +++ /dev/null @@ -1,10 +0,0 @@ -#!/usr/bin/env ruby - -vendored_cucumber_bin = Dir["#{File.dirname(__FILE__)}/../vendor/{gems,plugins}/cucumber*/bin/cucumber"].first -if vendored_cucumber_bin - load File.expand_path(vendored_cucumber_bin) -else - require 'rubygems' unless ENV['NO_RUBYGEMS'] - require 'cucumber' - load Cucumber::BINARY -end diff --git a/script/test b/script/test new file mode 100755 index 0000000..6a4d194 --- /dev/null +++ b/script/test @@ -0,0 +1,36 @@ +#!/bin/bash +# +# From Destroy All Software screencast #10, at: +# http://destroyallsoftware.com/screencasts/catalog/fast-tests-with-and-without-rails +# +# Put this in the script/ directory of your Rails app, then run it with a spec +# filename. If the spec uses spec_helper, it'll be run inside Bundler. +# Otherwise, it'll be run directly with whatever `rspec` executable is on the +# path. + +#set -e + +need_rails=1 + +if [ $# -gt 0 ]; then # we have args + filename=$1 + # Remove trailing line numbers from filename, e.g. spec/my_spec.rb:33 + grep_filename=`echo $1 | sed 's/:.*$//g'` + + #(set +e; grep -r 'spec_helper' $grep_filename) > /dev/null + (grep -r 'spec_helper' $grep_filename) > /dev/null + if [ $? -eq 1 ]; then # no match; we have a stand-alone spec + need_rails='' + fi +else # we have no args + filename='spec' +fi + +command='rspec --drb' + +if [ $need_rails ]; then + command="ruby -S bundle exec $command" +fi + +RAILS_ENV=test $command $filename + diff --git a/spec/controllers/admin/attachments_controller_spec.rb b/spec/controllers/admin/attachments_controller_spec.rb index 5d087e3..f67895a 100644 --- a/spec/controllers/admin/attachments_controller_spec.rb +++ b/spec/controllers/admin/attachments_controller_spec.rb @@ -1,5 +1,4 @@ require 'spec_helper' describe Admin::AttachmentsController do - end diff --git a/spec/factories/editor.rb b/spec/factories/editor.rb index b11f39a..66db498 100644 --- a/spec/factories/editor.rb +++ b/spec/factories/editor.rb @@ -1,6 +1,6 @@ Factory.define :editor, :class => Editor do |f| f.name "Ping Panter" - f.email "pink.panter@gmail.com" + f.sequence(:email) {|n| "pink.panter#{n}@gmail.com" } f.password "password" f.password_confirmation "password" end diff --git a/spec/models/editor_spec.rb b/spec/models/editor_spec.rb index f428b3a..255cd98 100644 --- a/spec/models/editor_spec.rb +++ b/spec/models/editor_spec.rb @@ -55,7 +55,7 @@ describe "authenticate" do it "should authenticate given valid email and password" do - editor = Factory.create(:editor) + editor = Factory.create(:editor, :email => 'pink.panter@gmail.com') Editor.authenticate('pink.panter@gmail.com', 'password').should == editor end diff --git a/spec/rcov.opts b/spec/rcov.opts deleted file mode 100644 index baf694c..0000000 --- a/spec/rcov.opts +++ /dev/null @@ -1,2 +0,0 @@ ---exclude "spec/*,gems/*" ---rails \ No newline at end of file diff --git a/spec/spec.opts b/spec/spec.opts deleted file mode 100644 index 7636dbe..0000000 --- a/spec/spec.opts +++ /dev/null @@ -1,4 +0,0 @@ ---colour ---format specdoc ---loadby mtime ---reverse diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 4693a1d..28a40b0 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,61 +1,47 @@ -# This file is copied to spec/ when you run 'rails generate rspec:install' -ENV["RAILS_ENV"] ||= 'test' -require File.expand_path("../../config/environment", __FILE__) -require 'rspec/rails' -require 'ruby-debug' -require 'rspec/autorun' - -# Requires supporting ruby files with custom matchers and macros, etc, -# in spec/support/ and its subdirectories. -Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f} - -RSpec.configure do |config| - # == Mock Framework - # - # If you prefer to use mocha, flexmock or RR, uncomment the appropriate line: - # - # config.mock_with :mocha - # config.mock_with :flexmock - # config.mock_with :rr - config.mock_with :rspec - - # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures - config.fixture_path = "#{::Rails.root}/spec/fixtures" - - # If you're not using ActiveRecord, or you'd prefer not to run each of your - # examples within a transaction, remove the following line or assign false - # instead of true. - config.use_transactional_fixtures = true - - # If true, the base class of anonymous controllers will be inferred - # automatically. This will be the default behavior in future versions of - # rspec-rails. - config.infer_base_class_for_anonymous_controllers = false +require 'rubygems' +require 'spork' + +Spork.prefork do + # This file is copied to spec/ when you run 'rails generate rspec:install' + ENV["RAILS_ENV"] ||= 'test' + require File.expand_path("../../config/environment", __FILE__) + require 'rspec/rails' + require 'ruby-debug' + require 'rspec/autorun' + + # Requires supporting ruby files with custom matchers and macros, etc, + # in spec/support/ and its subdirectories. + Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f} + + RSpec.configure do |config| + # == Mock Framework + # + # If you prefer to use mocha, flexmock or RR, uncomment the appropriate line: + # + # config.mock_with :mocha + # config.mock_with :flexmock + # config.mock_with :rr + config.mock_with :rspec + + # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures + config.fixture_path = "#{::Rails.root}/spec/fixtures" + + # If you're not using ActiveRecord, or you'd prefer not to run each of your + # examples within a transaction, remove the following line or assign false + # instead of true. + config.use_transactional_fixtures = true + + # If true, the base class of anonymous controllers will be inferred + # automatically. This will be the default behavior in future versions of + # rspec-rails. + config.infer_base_class_for_anonymous_controllers = false + end end -def login_as_editor - current_editor = Factory.create(:editor, :email => "editor@example.com") - controller.stub!(:current_editor).and_return(current_editor) - controller.stub!(:authenticate).and_return(:true) - current_editor -end +Spork.each_run do + # This code will be run each time you run your specs. -def login_as_admin - current_editor = Factory.create(:admin, :email => "admin@example.com") - controller.stub!(:current_editor).and_return(current_editor) - controller.stub!(:authenticate).and_return(:true) - current_editor end -shared_examples_for "protected resource" do - it "should protect resource" do - flash[:alert].should_not be_nil - response.should be_redirect - end -end - -shared_examples_for "accessible resource" do - it "should protect resource" do - flash[:alert].should be_nil - end -end +# require 'support/shared_examples' +# require 'support/helpers' diff --git a/spec/support/helpers.rb b/spec/support/helpers.rb new file mode 100644 index 0000000..8b3fc71 --- /dev/null +++ b/spec/support/helpers.rb @@ -0,0 +1,13 @@ +def login_as_editor + current_editor = Factory.create(:editor, :email => "editor@example.com") + controller.stub!(:current_editor).and_return(current_editor) + controller.stub!(:authenticate).and_return(:true) + current_editor +end + +def login_as_admin + current_editor = Factory.create(:admin, :email => "admin@example.com") + controller.stub!(:current_editor).and_return(current_editor) + controller.stub!(:authenticate).and_return(:true) + current_editor +end diff --git a/spec/support/shared_examples.rb b/spec/support/shared_examples.rb new file mode 100644 index 0000000..5a03f88 --- /dev/null +++ b/spec/support/shared_examples.rb @@ -0,0 +1,12 @@ +shared_examples_for "protected resource" do + it "should protect resource" do + flash[:alert].should_not be_nil + response.should be_redirect + end +end + +shared_examples_for "accessible resource" do + it "should protect resource" do + flash[:alert].should be_nil + end +end