mirror of
https://github.com/thoughtbot/shoulda-matchers.git
synced 2022-11-09 12:01:38 -05:00
Extracted the context framework, switched to rspec
This commit is contained in:
parent
2320a8c539
commit
6aca71765a
200 changed files with 1735 additions and 3531 deletions
2
.bundle/config
Normal file
2
.bundle/config
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
---
|
||||||
|
BUNDLE_DISABLE_SHARED_GEMS: "1"
|
9
Gemfile
Normal file
9
Gemfile
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
source 'http://rubygems.org'
|
||||||
|
|
||||||
|
gem 'rails', '3.0.0.beta4'
|
||||||
|
gem 'sqlite3-ruby', :require => 'sqlite3'
|
||||||
|
gem 'mocha'
|
||||||
|
gem 'rspec-rails', '2.0.0.beta.12'
|
||||||
|
gem 'ruby-debug'
|
||||||
|
gem 'cucumber'
|
||||||
|
|
115
Gemfile.lock
Normal file
115
Gemfile.lock
Normal file
|
@ -0,0 +1,115 @@
|
||||||
|
GEM
|
||||||
|
remote: http://rubygems.org/
|
||||||
|
specs:
|
||||||
|
abstract (1.0.0)
|
||||||
|
actionmailer (3.0.0.beta4)
|
||||||
|
actionpack (= 3.0.0.beta4)
|
||||||
|
mail (~> 2.2.3)
|
||||||
|
actionpack (3.0.0.beta4)
|
||||||
|
activemodel (= 3.0.0.beta4)
|
||||||
|
activesupport (= 3.0.0.beta4)
|
||||||
|
builder (~> 2.1.2)
|
||||||
|
erubis (~> 2.6.5)
|
||||||
|
i18n (~> 0.4.1)
|
||||||
|
rack (~> 1.1.0)
|
||||||
|
rack-mount (~> 0.6.3)
|
||||||
|
rack-test (~> 0.5.4)
|
||||||
|
tzinfo (~> 0.3.16)
|
||||||
|
activemodel (3.0.0.beta4)
|
||||||
|
activesupport (= 3.0.0.beta4)
|
||||||
|
builder (~> 2.1.2)
|
||||||
|
i18n (~> 0.4.1)
|
||||||
|
activerecord (3.0.0.beta4)
|
||||||
|
activemodel (= 3.0.0.beta4)
|
||||||
|
activesupport (= 3.0.0.beta4)
|
||||||
|
arel (~> 0.4.0)
|
||||||
|
tzinfo (~> 0.3.16)
|
||||||
|
activeresource (3.0.0.beta4)
|
||||||
|
activemodel (= 3.0.0.beta4)
|
||||||
|
activesupport (= 3.0.0.beta4)
|
||||||
|
activesupport (3.0.0.beta4)
|
||||||
|
arel (0.4.0)
|
||||||
|
activesupport (>= 3.0.0.beta)
|
||||||
|
builder (2.1.2)
|
||||||
|
columnize (0.3.1)
|
||||||
|
cucumber (0.9.4)
|
||||||
|
builder (~> 2.1.2)
|
||||||
|
diff-lcs (~> 1.1.2)
|
||||||
|
gherkin (~> 2.2.9)
|
||||||
|
json (~> 1.4.6)
|
||||||
|
term-ansicolor (~> 1.0.5)
|
||||||
|
diff-lcs (1.1.2)
|
||||||
|
erubis (2.6.6)
|
||||||
|
abstract (>= 1.0.0)
|
||||||
|
gherkin (2.2.9)
|
||||||
|
json (~> 1.4.6)
|
||||||
|
term-ansicolor (~> 1.0.5)
|
||||||
|
i18n (0.4.1)
|
||||||
|
json (1.4.6)
|
||||||
|
linecache (0.43)
|
||||||
|
mail (2.2.12)
|
||||||
|
activesupport (>= 2.3.6)
|
||||||
|
i18n (>= 0.4.0)
|
||||||
|
mime-types (~> 1.16)
|
||||||
|
treetop (~> 1.4.8)
|
||||||
|
mime-types (1.16)
|
||||||
|
mocha (0.9.10)
|
||||||
|
rake
|
||||||
|
nokogiri (1.4.4)
|
||||||
|
polyglot (0.3.1)
|
||||||
|
rack (1.1.0)
|
||||||
|
rack-mount (0.6.13)
|
||||||
|
rack (>= 1.0.0)
|
||||||
|
rack-test (0.5.6)
|
||||||
|
rack (>= 1.0)
|
||||||
|
rails (3.0.0.beta4)
|
||||||
|
actionmailer (= 3.0.0.beta4)
|
||||||
|
actionpack (= 3.0.0.beta4)
|
||||||
|
activerecord (= 3.0.0.beta4)
|
||||||
|
activeresource (= 3.0.0.beta4)
|
||||||
|
activesupport (= 3.0.0.beta4)
|
||||||
|
bundler (>= 0.9.26)
|
||||||
|
railties (= 3.0.0.beta4)
|
||||||
|
railties (3.0.0.beta4)
|
||||||
|
actionpack (= 3.0.0.beta4)
|
||||||
|
activesupport (= 3.0.0.beta4)
|
||||||
|
rake (>= 0.8.3)
|
||||||
|
thor (~> 0.13.6)
|
||||||
|
rake (0.8.7)
|
||||||
|
rspec (2.0.0.beta.12)
|
||||||
|
rspec-core (= 2.0.0.beta.12)
|
||||||
|
rspec-expectations (= 2.0.0.beta.12)
|
||||||
|
rspec-mocks (= 2.0.0.beta.12)
|
||||||
|
rspec-core (2.0.0.beta.12)
|
||||||
|
rspec-expectations (2.0.0.beta.12)
|
||||||
|
diff-lcs (>= 1.1.2)
|
||||||
|
rspec-mocks (2.0.0.beta.12)
|
||||||
|
rspec-rails (2.0.0.beta.12)
|
||||||
|
rspec (= 2.0.0.beta.12)
|
||||||
|
webrat (>= 0.7.0)
|
||||||
|
ruby-debug (0.10.3)
|
||||||
|
columnize (>= 0.1)
|
||||||
|
ruby-debug-base (~> 0.10.3.0)
|
||||||
|
ruby-debug-base (0.10.3)
|
||||||
|
linecache (>= 0.3)
|
||||||
|
sqlite3-ruby (1.3.2)
|
||||||
|
term-ansicolor (1.0.5)
|
||||||
|
thor (0.13.8)
|
||||||
|
treetop (1.4.9)
|
||||||
|
polyglot (>= 0.3.1)
|
||||||
|
tzinfo (0.3.23)
|
||||||
|
webrat (0.7.2)
|
||||||
|
nokogiri (>= 1.2.0)
|
||||||
|
rack (>= 1.0)
|
||||||
|
rack-test (>= 0.5.3)
|
||||||
|
|
||||||
|
PLATFORMS
|
||||||
|
ruby
|
||||||
|
|
||||||
|
DEPENDENCIES
|
||||||
|
cucumber
|
||||||
|
mocha
|
||||||
|
rails (= 3.0.0.beta4)
|
||||||
|
rspec-rails (= 2.0.0.beta.12)
|
||||||
|
ruby-debug
|
||||||
|
sqlite3-ruby
|
34
Rakefile
34
Rakefile
|
@ -1,25 +1,13 @@
|
||||||
require 'rubygems'
|
require 'rubygems'
|
||||||
|
require 'bundler/setup'
|
||||||
require 'rake'
|
require 'rake'
|
||||||
require 'rake/testtask'
|
|
||||||
require 'rake/rdoctask'
|
require 'rake/rdoctask'
|
||||||
require 'rake/gempackagetask'
|
require 'rake/gempackagetask'
|
||||||
begin
|
require 'rspec/core/rake_task'
|
||||||
require 'cucumber/rake/task'
|
require 'cucumber/rake/task'
|
||||||
rescue LoadError
|
|
||||||
warn "couldn't load cucumber, skipping"
|
|
||||||
end
|
|
||||||
|
|
||||||
$LOAD_PATH.unshift("lib")
|
$LOAD_PATH.unshift("lib")
|
||||||
require 'shoulda/version'
|
require 'shoulda/version'
|
||||||
load 'tasks/shoulda.rake'
|
|
||||||
|
|
||||||
# Test::Unit::UI::VERBOSE
|
|
||||||
test_files_pattern = 'test/{unit,functional,other,matchers}/**/*_test.rb'
|
|
||||||
Rake::TestTask.new do |t|
|
|
||||||
t.libs << 'lib' << 'test'
|
|
||||||
t.pattern = test_files_pattern
|
|
||||||
t.verbose = false
|
|
||||||
end
|
|
||||||
|
|
||||||
Rake::RDocTask.new { |rdoc|
|
Rake::RDocTask.new { |rdoc|
|
||||||
rdoc.rdoc_dir = 'doc'
|
rdoc.rdoc_dir = 'doc'
|
||||||
|
@ -29,11 +17,15 @@ Rake::RDocTask.new { |rdoc|
|
||||||
rdoc.rdoc_files.include('README.rdoc', 'CONTRIBUTION_GUIDELINES.rdoc', 'lib/**/*.rb')
|
rdoc.rdoc_files.include('README.rdoc', 'CONTRIBUTION_GUIDELINES.rdoc', 'lib/**/*.rb')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RSpec::Core::RakeTask.new do |t|
|
||||||
|
t.pattern = "spec/**/*_spec.rb"
|
||||||
|
end
|
||||||
|
|
||||||
desc "Run code-coverage analysis using rcov"
|
desc "Run code-coverage analysis using rcov"
|
||||||
task :coverage do
|
RSpec::Core::RakeTask.new(:coverage) do |t|
|
||||||
rm_rf "coverage"
|
t.rcov = true
|
||||||
files = Dir[test_files_pattern]
|
t.rcov_opts = %{--exclude osx\/objc,spec,gems\/ --failure-threshold 100}
|
||||||
system "rcov --rails --sort coverage -Ilib #{files.join(' ')}"
|
t.pattern = "spec/**/*_spec.rb"
|
||||||
end
|
end
|
||||||
|
|
||||||
eval("$specification = begin; #{IO.read('shoulda.gemspec')}; end")
|
eval("$specification = begin; #{IO.read('shoulda.gemspec')}; end")
|
||||||
|
@ -51,6 +43,6 @@ Cucumber::Rake::Task.new do |t|
|
||||||
t.profile = 'default'
|
t.profile = 'default'
|
||||||
end
|
end
|
||||||
|
|
||||||
desc 'Default: run test and cucumber features for support versions'
|
desc 'Default: run specs and cucumber features'
|
||||||
task :default => [:test, :cucumber]
|
task :default => [:spec, :cucumber]
|
||||||
|
|
||||||
|
|
|
@ -1,42 +0,0 @@
|
||||||
#!/usr/bin/env ruby
|
|
||||||
require 'fileutils'
|
|
||||||
require 'tmpdir'
|
|
||||||
|
|
||||||
TMP = Dir::tmpdir
|
|
||||||
|
|
||||||
def usage(msg = nil)
|
|
||||||
puts "Error: #{msg}" if msg
|
|
||||||
puts if msg
|
|
||||||
puts "Usage: #{File.basename(__FILE__)} normal_test_file.rb"
|
|
||||||
puts
|
|
||||||
puts "Will convert an existing test file with names like "
|
|
||||||
puts
|
|
||||||
puts " def test_should_do_stuff"
|
|
||||||
puts " ..."
|
|
||||||
puts " end"
|
|
||||||
puts
|
|
||||||
puts "to one using the new syntax: "
|
|
||||||
puts
|
|
||||||
puts " should \"be super cool\" do"
|
|
||||||
puts " ..."
|
|
||||||
puts " end"
|
|
||||||
puts
|
|
||||||
puts "A copy of the old file will be left under #{TMP} in case\nthis script just seriously screws up"
|
|
||||||
puts
|
|
||||||
exit (msg ? 2 : 0)
|
|
||||||
end
|
|
||||||
|
|
||||||
usage("Wrong number of arguments.") unless ARGV.size == 1
|
|
||||||
usage("Temp directory '#{TMP}' is not valid. Set TMPDIR environment variable to a writeable directory.") unless File.directory?(TMP) && File.writable?(TMP)
|
|
||||||
|
|
||||||
file = ARGV.shift
|
|
||||||
tmpfile = File.join(TMP, File.basename(file))
|
|
||||||
usage("File '#{file}' doesn't exist") unless File.exists?(file)
|
|
||||||
|
|
||||||
FileUtils.cp(file, tmpfile)
|
|
||||||
contents = File.read(tmpfile)
|
|
||||||
contents.gsub!(/def test_should_(\S+)/) {|line| "should \"#{$1.tr('_', ' ')}\" do"}
|
|
||||||
contents.gsub!(/def test_(\S+)/) {|line| "should \"RENAME ME: test #{$1.tr('_', ' ')}\" do"}
|
|
||||||
File.open(file, 'w') { |f| f.write(contents) }
|
|
||||||
|
|
||||||
puts "File '#{file}' has been converted to 'should' syntax. Old version has been stored in '#{tmpfile}'"
|
|
|
@ -29,7 +29,7 @@ When /^I run the rspec generator$/ do
|
||||||
end
|
end
|
||||||
|
|
||||||
When /^I configure the application to use rspec\-rails$/ do
|
When /^I configure the application to use rspec\-rails$/ do
|
||||||
append_to_gemfile "gem 'rspec-rails', '>= 2.0.0.beta.12'"
|
append_to_gemfile "gem 'rspec-rails', '= 2.0.0.beta.12'"
|
||||||
steps %{And I run "bundle install"}
|
steps %{And I run "bundle install"}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
1
init.rb
1
init.rb
|
@ -1 +0,0 @@
|
||||||
require File.join(File.dirname(__FILE__), 'rails', 'init')
|
|
|
@ -5,3 +5,4 @@ if defined?(RSpec)
|
||||||
else
|
else
|
||||||
require 'shoulda/integrations/test_unit'
|
require 'shoulda/integrations/test_unit'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -1,19 +1,39 @@
|
||||||
require 'shoulda'
|
require 'shoulda/action_controller/assign_to_matcher'
|
||||||
require 'shoulda/action_controller/matchers'
|
require 'shoulda/action_controller/filter_param_matcher'
|
||||||
|
require 'shoulda/action_controller/set_the_flash_matcher'
|
||||||
|
require 'shoulda/action_controller/render_with_layout_matcher'
|
||||||
|
require 'shoulda/action_controller/respond_with_matcher'
|
||||||
|
require 'shoulda/action_controller/respond_with_content_type_matcher'
|
||||||
|
require 'shoulda/action_controller/set_session_matcher'
|
||||||
|
require 'shoulda/action_controller/route_matcher'
|
||||||
|
require 'shoulda/action_controller/redirect_to_matcher'
|
||||||
|
require 'shoulda/action_controller/render_template_matcher'
|
||||||
|
|
||||||
module Test # :nodoc: all
|
module Shoulda # :nodoc:
|
||||||
module Unit
|
module ActionController # :nodoc:
|
||||||
class TestCase
|
|
||||||
include Shoulda::ActionController::Matchers
|
# By using the matchers you can quickly and easily create concise and
|
||||||
extend Shoulda::ActionController::Matchers
|
# easy to read test suites.
|
||||||
end
|
#
|
||||||
end
|
# This code segment:
|
||||||
end
|
#
|
||||||
|
# describe UsersController, "on GET to show with a valid id" do
|
||||||
if defined?(ActionController::TestCase)
|
# before(:each) do
|
||||||
class ActionController::TestCase
|
# get :show, :id => User.first.to_param
|
||||||
def subject
|
# end
|
||||||
@controller
|
#
|
||||||
|
# it { should assign_to(:user) }
|
||||||
|
# it { should respond_with(:success) }
|
||||||
|
# it { should render_template(:show) }
|
||||||
|
# it { should not_set_the_flash) }
|
||||||
|
#
|
||||||
|
# it "should do something else really cool" do
|
||||||
|
# assigns[:user].id.should == 1
|
||||||
|
# end
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# Would produce 5 tests for the show action
|
||||||
|
module Matchers
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
50
lib/shoulda/action_controller/filter_param_matcher.rb
Normal file
50
lib/shoulda/action_controller/filter_param_matcher.rb
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
module Shoulda # :nodoc:
|
||||||
|
module ActionController # :nodoc:
|
||||||
|
module Matchers
|
||||||
|
|
||||||
|
# Ensures that filter_parameter_logging is set for the specified key.
|
||||||
|
#
|
||||||
|
# Example:
|
||||||
|
#
|
||||||
|
# it { should filter_param(:password) }
|
||||||
|
def filter_param(key)
|
||||||
|
FilterParamMatcher.new(key)
|
||||||
|
end
|
||||||
|
|
||||||
|
class FilterParamMatcher # :nodoc:
|
||||||
|
|
||||||
|
def initialize(key)
|
||||||
|
@key = key.to_s
|
||||||
|
end
|
||||||
|
|
||||||
|
def matches?(controller)
|
||||||
|
@controller = controller
|
||||||
|
filters_key?
|
||||||
|
end
|
||||||
|
|
||||||
|
def failure_message
|
||||||
|
"Expected #{@key} to be filtered; filtered keys: #{filtered_keys.join(', ')}"
|
||||||
|
end
|
||||||
|
|
||||||
|
def negative_failure_message
|
||||||
|
"Did not expect #{@key} to be filtered"
|
||||||
|
end
|
||||||
|
|
||||||
|
def description
|
||||||
|
"filter #{@key}"
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def filters_key?
|
||||||
|
filtered_keys.include?(@key)
|
||||||
|
end
|
||||||
|
|
||||||
|
def filtered_keys
|
||||||
|
Rails.application.config.filter_parameters.map { |filter| filter.to_s }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,39 +0,0 @@
|
||||||
require 'shoulda/action_controller/matchers/assign_to_matcher'
|
|
||||||
require 'shoulda/action_controller/matchers/filter_param_matcher'
|
|
||||||
require 'shoulda/action_controller/matchers/set_the_flash_matcher'
|
|
||||||
require 'shoulda/action_controller/matchers/render_with_layout_matcher'
|
|
||||||
require 'shoulda/action_controller/matchers/respond_with_matcher'
|
|
||||||
require 'shoulda/action_controller/matchers/respond_with_content_type_matcher'
|
|
||||||
require 'shoulda/action_controller/matchers/set_session_matcher'
|
|
||||||
require 'shoulda/action_controller/matchers/route_matcher'
|
|
||||||
require 'shoulda/action_controller/matchers/redirect_to_matcher'
|
|
||||||
require 'shoulda/action_controller/matchers/render_template_matcher'
|
|
||||||
|
|
||||||
module Shoulda # :nodoc:
|
|
||||||
module ActionController # :nodoc:
|
|
||||||
|
|
||||||
# By using the matchers you can quickly and easily create concise and
|
|
||||||
# easy to read test suites.
|
|
||||||
#
|
|
||||||
# This code segment:
|
|
||||||
#
|
|
||||||
# describe UsersController, "on GET to show with a valid id" do
|
|
||||||
# before(:each) do
|
|
||||||
# get :show, :id => User.first.to_param
|
|
||||||
# end
|
|
||||||
#
|
|
||||||
# it { should assign_to(:user) }
|
|
||||||
# it { should respond_with(:success) }
|
|
||||||
# it { should render_template(:show) }
|
|
||||||
# it { should not_set_the_flash) }
|
|
||||||
#
|
|
||||||
# it "should do something else really cool" do
|
|
||||||
# assigns[:user].id.should == 1
|
|
||||||
# end
|
|
||||||
# end
|
|
||||||
#
|
|
||||||
# Would produce 5 tests for the show action
|
|
||||||
module Matchers
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,74 +0,0 @@
|
||||||
module Shoulda # :nodoc:
|
|
||||||
module ActionController # :nodoc:
|
|
||||||
module Matchers
|
|
||||||
|
|
||||||
# Ensures that filter_parameter_logging is set for the specified key.
|
|
||||||
#
|
|
||||||
# Example:
|
|
||||||
#
|
|
||||||
# it { should filter_param(:password) }
|
|
||||||
def filter_param(key)
|
|
||||||
FilterParamMatcher.new(key)
|
|
||||||
end
|
|
||||||
|
|
||||||
class FilterParamMatcher # :nodoc:
|
|
||||||
|
|
||||||
def initialize(key)
|
|
||||||
@key = key.to_s
|
|
||||||
end
|
|
||||||
|
|
||||||
def matches?(controller)
|
|
||||||
@controller = controller
|
|
||||||
filters_params? && filters_key?
|
|
||||||
end
|
|
||||||
|
|
||||||
def failure_message
|
|
||||||
"Expected #{@key} to be filtered"
|
|
||||||
end
|
|
||||||
|
|
||||||
def negative_failure_message
|
|
||||||
"Did not expect #{@key} to be filtered"
|
|
||||||
end
|
|
||||||
|
|
||||||
def description
|
|
||||||
"filter #{@key}"
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def filters_params?
|
|
||||||
@controller.respond_to?(:filter_parameters) ||
|
|
||||||
request.respond_to?(:filtered_parameters)
|
|
||||||
end
|
|
||||||
|
|
||||||
def filters_key?
|
|
||||||
filtered_value == '[FILTERED]'
|
|
||||||
end
|
|
||||||
|
|
||||||
def filtered_value
|
|
||||||
if request.respond_to?(:filtered_parameters)
|
|
||||||
filtered_request_value
|
|
||||||
else
|
|
||||||
filtered_controller_value
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def filtered_controller_value
|
|
||||||
filtered = @controller.send(:filter_parameters,
|
|
||||||
@key.to_s => @key.to_s)
|
|
||||||
filtered[@key.to_s]
|
|
||||||
end
|
|
||||||
|
|
||||||
def filtered_request_value
|
|
||||||
request.env['action_dispatch.request.parameters'] = { @key.to_s => 'value' }
|
|
||||||
request.filtered_parameters[@key.to_s]
|
|
||||||
end
|
|
||||||
|
|
||||||
def request
|
|
||||||
@request ||= ::ActionController::TestRequest.new
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -10,10 +10,10 @@ module Shoulda # :nodoc:
|
||||||
# it { should render_with_layout(:special) }
|
# it { should render_with_layout(:special) }
|
||||||
# it { should_not render_with_layout }
|
# it { should_not render_with_layout }
|
||||||
def render_with_layout(expected_layout = nil)
|
def render_with_layout(expected_layout = nil)
|
||||||
RenderWithLayout.new(expected_layout)
|
RenderWithLayoutMatcher.new(expected_layout).in_context(self)
|
||||||
end
|
end
|
||||||
|
|
||||||
class RenderWithLayout # :nodoc:
|
class RenderWithLayoutMatcher # :nodoc:
|
||||||
|
|
||||||
def initialize(expected_layout)
|
def initialize(expected_layout)
|
||||||
@expected_layout = expected_layout.to_s unless expected_layout.nil?
|
@expected_layout = expected_layout.to_s unless expected_layout.nil?
|
|
@ -67,15 +67,9 @@ module Shoulda # :nodoc:
|
||||||
|
|
||||||
def flash
|
def flash
|
||||||
return @flash if @flash
|
return @flash if @flash
|
||||||
flash_and_now = @controller.request.session["flash"].dup if @controller.request.session["flash"]
|
@flash = @controller.flash.dup
|
||||||
flash = @controller.send(:flash)
|
@flash.sweep unless @now
|
||||||
|
@flash
|
||||||
@flash = if @now
|
|
||||||
flash.keys.each {|key| flash_and_now.delete(key) }
|
|
||||||
flash_and_now
|
|
||||||
else
|
|
||||||
flash
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def expectation
|
def expectation
|
|
@ -1,11 +1,22 @@
|
||||||
require 'shoulda'
|
require 'shoulda/action_mailer/have_sent_email'
|
||||||
require 'shoulda/action_mailer/matchers'
|
|
||||||
|
|
||||||
module Test # :nodoc: all
|
module Shoulda # :nodoc:
|
||||||
module Unit
|
module ActionMailer # :nodoc:
|
||||||
class TestCase
|
# = Matchers for your mailers
|
||||||
include Shoulda::ActionMailer::Matchers
|
#
|
||||||
extend Shoulda::ActionMailer::Matchers
|
# This matcher will test that email is sent properly
|
||||||
|
#
|
||||||
|
# describe User do
|
||||||
|
# it { should have_sent_email.with_subject(/is spam$/) }
|
||||||
|
# it { should have_sent_email.from('do-not-reply@example.com') }
|
||||||
|
# it { should have_sent_email.with_body(/is spam\./) }
|
||||||
|
# it { should have_sent_email.to('myself@me.com') }
|
||||||
|
# it { should have_sent_email.with_subject(/spam/).
|
||||||
|
# from('do-not-reply@example.com').
|
||||||
|
# with_body(/spam/).
|
||||||
|
# to('myself@me.com') }
|
||||||
|
# end
|
||||||
|
module Matchers
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,22 +0,0 @@
|
||||||
require 'shoulda/action_mailer/matchers/have_sent_email'
|
|
||||||
|
|
||||||
module Shoulda # :nodoc:
|
|
||||||
module ActionMailer # :nodoc:
|
|
||||||
# = Matchers for your mailers
|
|
||||||
#
|
|
||||||
# This matcher will test that email is sent properly
|
|
||||||
#
|
|
||||||
# describe User do
|
|
||||||
# it { should have_sent_email.with_subject(/is spam$/) }
|
|
||||||
# it { should have_sent_email.from('do-not-reply@example.com') }
|
|
||||||
# it { should have_sent_email.with_body(/is spam\./) }
|
|
||||||
# it { should have_sent_email.to('myself@me.com') }
|
|
||||||
# it { should have_sent_email.with_subject(/spam/).
|
|
||||||
# from('do-not-reply@example.com').
|
|
||||||
# with_body(/spam/).
|
|
||||||
# to('myself@me.com') }
|
|
||||||
# end
|
|
||||||
module Matchers
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,12 +1,42 @@
|
||||||
require 'shoulda'
|
|
||||||
require 'shoulda/active_record/helpers'
|
require 'shoulda/active_record/helpers'
|
||||||
require 'shoulda/active_record/matchers'
|
require 'shoulda/active_record/validation_matcher'
|
||||||
|
require 'shoulda/active_record/allow_value_matcher'
|
||||||
|
require 'shoulda/active_record/ensure_length_of_matcher'
|
||||||
|
require 'shoulda/active_record/ensure_inclusion_of_matcher'
|
||||||
|
require 'shoulda/active_record/validate_presence_of_matcher'
|
||||||
|
require 'shoulda/active_record/validate_format_of_matcher'
|
||||||
|
require 'shoulda/active_record/validate_uniqueness_of_matcher'
|
||||||
|
require 'shoulda/active_record/validate_acceptance_of_matcher'
|
||||||
|
require 'shoulda/active_record/validate_numericality_of_matcher'
|
||||||
|
require 'shoulda/active_record/association_matcher'
|
||||||
|
require 'shoulda/active_record/have_db_column_matcher'
|
||||||
|
require 'shoulda/active_record/have_db_index_matcher'
|
||||||
|
require 'shoulda/active_record/have_readonly_attribute_matcher'
|
||||||
|
require 'shoulda/active_record/allow_mass_assignment_of_matcher'
|
||||||
|
|
||||||
module Test # :nodoc: all
|
|
||||||
module Unit
|
module Shoulda # :nodoc:
|
||||||
class TestCase
|
module ActiveRecord # :nodoc:
|
||||||
include Shoulda::ActiveRecord::Matchers
|
# = Matchers for your active record models
|
||||||
extend Shoulda::ActiveRecord::Matchers
|
#
|
||||||
|
# These matchers will test most of the validations and associations for your
|
||||||
|
# ActiveRecord models.
|
||||||
|
#
|
||||||
|
# describe User do
|
||||||
|
# it { should validate_presence_of(:name) }
|
||||||
|
# it { should validate_presence_of(:phone_number) }
|
||||||
|
# %w(abcd 1234).each do |value|
|
||||||
|
# it { should_not allow_value(value).for(:phone_number) }
|
||||||
|
# end
|
||||||
|
# it { should allow_value("(123) 456-7890").for(:phone_number) }
|
||||||
|
# it { should_not allow_mass_assignment_of(:password) }
|
||||||
|
# it { should have_one(:profile) }
|
||||||
|
# it { should have_many(:dogs) }
|
||||||
|
# it { should have_many(:messes).through(:dogs) }
|
||||||
|
# it { should belong_to(:lover) }
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
module Matchers
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,42 +0,0 @@
|
||||||
require 'shoulda/active_record/helpers'
|
|
||||||
require 'shoulda/active_record/matchers/validation_matcher'
|
|
||||||
require 'shoulda/active_record/matchers/allow_value_matcher'
|
|
||||||
require 'shoulda/active_record/matchers/ensure_length_of_matcher'
|
|
||||||
require 'shoulda/active_record/matchers/ensure_inclusion_of_matcher'
|
|
||||||
require 'shoulda/active_record/matchers/validate_presence_of_matcher'
|
|
||||||
require 'shoulda/active_record/matchers/validate_format_of_matcher'
|
|
||||||
require 'shoulda/active_record/matchers/validate_uniqueness_of_matcher'
|
|
||||||
require 'shoulda/active_record/matchers/validate_acceptance_of_matcher'
|
|
||||||
require 'shoulda/active_record/matchers/validate_numericality_of_matcher'
|
|
||||||
require 'shoulda/active_record/matchers/association_matcher'
|
|
||||||
require 'shoulda/active_record/matchers/have_db_column_matcher'
|
|
||||||
require 'shoulda/active_record/matchers/have_db_index_matcher'
|
|
||||||
require 'shoulda/active_record/matchers/have_readonly_attribute_matcher'
|
|
||||||
require 'shoulda/active_record/matchers/allow_mass_assignment_of_matcher'
|
|
||||||
|
|
||||||
|
|
||||||
module Shoulda # :nodoc:
|
|
||||||
module ActiveRecord # :nodoc:
|
|
||||||
# = Matchers for your active record models
|
|
||||||
#
|
|
||||||
# These matchers will test most of the validations and associations for your
|
|
||||||
# ActiveRecord models.
|
|
||||||
#
|
|
||||||
# describe User do
|
|
||||||
# it { should validate_presence_of(:name) }
|
|
||||||
# it { should validate_presence_of(:phone_number) }
|
|
||||||
# %w(abcd 1234).each do |value|
|
|
||||||
# it { should_not allow_value(value).for(:phone_number) }
|
|
||||||
# end
|
|
||||||
# it { should allow_value("(123) 456-7890").for(:phone_number) }
|
|
||||||
# it { should_not allow_mass_assignment_of(:password) }
|
|
||||||
# it { should have_one(:profile) }
|
|
||||||
# it { should have_many(:dogs) }
|
|
||||||
# it { should have_many(:messes).through(:dogs) }
|
|
||||||
# it { should belong_to(:lover) }
|
|
||||||
# end
|
|
||||||
#
|
|
||||||
module Matchers
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,79 +0,0 @@
|
||||||
module Shoulda # :nodoc:
|
|
||||||
module Assertions
|
|
||||||
# Asserts that two arrays contain the same elements, the same number of times. Essentially ==, but unordered.
|
|
||||||
#
|
|
||||||
# assert_same_elements([:a, :b, :c], [:c, :a, :b]) => passes
|
|
||||||
def assert_same_elements(a1, a2, msg = nil)
|
|
||||||
[:select, :inject, :size].each do |m|
|
|
||||||
[a1, a2].each {|a| assert_respond_to(a, m, "Are you sure that #{a.inspect} is an array? It doesn't respond to #{m}.") }
|
|
||||||
end
|
|
||||||
|
|
||||||
assert a1h = a1.inject({}) { |h,e| h[e] = a1.select { |i| i == e }.size; h }
|
|
||||||
assert a2h = a2.inject({}) { |h,e| h[e] = a2.select { |i| i == e }.size; h }
|
|
||||||
|
|
||||||
assert_equal(a1h, a2h, msg)
|
|
||||||
end
|
|
||||||
|
|
||||||
# Asserts that the given collection contains item x. If x is a regular expression, ensure that
|
|
||||||
# at least one element from the collection matches x. +extra_msg+ is appended to the error message if the assertion fails.
|
|
||||||
#
|
|
||||||
# assert_contains(['a', '1'], /\d/) => passes
|
|
||||||
# assert_contains(['a', '1'], 'a') => passes
|
|
||||||
# assert_contains(['a', '1'], /not there/) => fails
|
|
||||||
def assert_contains(collection, x, extra_msg = "")
|
|
||||||
collection = [collection] unless collection.is_a?(Array)
|
|
||||||
msg = "#{x.inspect} not found in #{collection.to_a.inspect} #{extra_msg}"
|
|
||||||
case x
|
|
||||||
when Regexp
|
|
||||||
assert(collection.detect { |e| e =~ x }, msg)
|
|
||||||
else
|
|
||||||
assert(collection.include?(x), msg)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# Asserts that the given collection does not contain item x. If x is a regular expression, ensure that
|
|
||||||
# none of the elements from the collection match x.
|
|
||||||
def assert_does_not_contain(collection, x, extra_msg = "")
|
|
||||||
collection = [collection] unless collection.is_a?(Array)
|
|
||||||
msg = "#{x.inspect} found in #{collection.to_a.inspect} " + extra_msg
|
|
||||||
case x
|
|
||||||
when Regexp
|
|
||||||
assert(!collection.detect { |e| e =~ x }, msg)
|
|
||||||
else
|
|
||||||
assert(!collection.include?(x), msg)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# Asserts that the given matcher returns true when +target+ is passed to #matches?
|
|
||||||
def assert_accepts(matcher, target, options = {})
|
|
||||||
if matcher.respond_to?(:in_context)
|
|
||||||
matcher.in_context(self)
|
|
||||||
end
|
|
||||||
|
|
||||||
if matcher.matches?(target)
|
|
||||||
assert_block { true }
|
|
||||||
if options[:message]
|
|
||||||
assert_match options[:message], matcher.negative_failure_message
|
|
||||||
end
|
|
||||||
else
|
|
||||||
assert_block(matcher.failure_message) { false }
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# Asserts that the given matcher returns false when +target+ is passed to #matches?
|
|
||||||
def assert_rejects(matcher, target, options = {})
|
|
||||||
if matcher.respond_to?(:in_context)
|
|
||||||
matcher.in_context(self)
|
|
||||||
end
|
|
||||||
|
|
||||||
unless matcher.matches?(target)
|
|
||||||
assert_block { true }
|
|
||||||
if options[:message]
|
|
||||||
assert_match options[:message], matcher.failure_message
|
|
||||||
end
|
|
||||||
else
|
|
||||||
assert_block(matcher.negative_failure_message) { false }
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,46 +0,0 @@
|
||||||
module Shoulda # :nodoc:
|
|
||||||
# Call autoload_macros when you want to load test macros automatically in a non-Rails
|
|
||||||
# project (it's done automatically for Rails projects).
|
|
||||||
# You don't need to specify ROOT/test/shoulda_macros explicitly. Your custom macros
|
|
||||||
# are loaded automatically when you call autoload_macros.
|
|
||||||
#
|
|
||||||
# The first argument is the path to you application's root directory.
|
|
||||||
# All following arguments are directories relative to your root, which contain
|
|
||||||
# shoulda_macros subdirectories. These directories support the same kinds of globs as the
|
|
||||||
# Dir class.
|
|
||||||
#
|
|
||||||
# Basic usage (from a test_helper):
|
|
||||||
# Shoulda.autoload_macros(File.dirname(__FILE__) + '/..')
|
|
||||||
# will load everything in
|
|
||||||
# - your_app/test/shoulda_macros
|
|
||||||
#
|
|
||||||
# To load vendored macros as well:
|
|
||||||
# Shoulda.autoload_macros(APP_ROOT, 'vendor/*')
|
|
||||||
# will load everything in
|
|
||||||
# - APP_ROOT/vendor/*/shoulda_macros
|
|
||||||
# - APP_ROOT/test/shoulda_macros
|
|
||||||
#
|
|
||||||
# To load macros in an app with a vendor directory laid out like Rails':
|
|
||||||
# Shoulda.autoload_macros(APP_ROOT, 'vendor/{plugins,gems}/*')
|
|
||||||
# or
|
|
||||||
# Shoulda.autoload_macros(APP_ROOT, 'vendor/plugins/*', 'vendor/gems/*')
|
|
||||||
# will load everything in
|
|
||||||
# - APP_ROOT/vendor/plugins/*/shoulda_macros
|
|
||||||
# - APP_ROOT/vendor/gems/*/shoulda_macros
|
|
||||||
# - APP_ROOT/test/shoulda_macros
|
|
||||||
#
|
|
||||||
# If you prefer to stick testing dependencies away from your production dependencies:
|
|
||||||
# Shoulda.autoload_macros(APP_ROOT, 'vendor/*', 'test/vendor/*')
|
|
||||||
# will load everything in
|
|
||||||
# - APP_ROOT/vendor/*/shoulda_macros
|
|
||||||
# - APP_ROOT/test/vendor/*/shoulda_macros
|
|
||||||
# - APP_ROOT/test/shoulda_macros
|
|
||||||
def self.autoload_macros(root, *dirs)
|
|
||||||
dirs << File.join('test')
|
|
||||||
complete_dirs = dirs.map{|d| File.join(root, d, 'shoulda_macros')}
|
|
||||||
all_files = complete_dirs.inject([]){ |files, dir| files + Dir[File.join(dir, '*.rb')] }
|
|
||||||
all_files.each do |file|
|
|
||||||
require file
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,441 +0,0 @@
|
||||||
module Shoulda
|
|
||||||
class << self
|
|
||||||
attr_accessor :contexts
|
|
||||||
def contexts # :nodoc:
|
|
||||||
@contexts ||= []
|
|
||||||
end
|
|
||||||
|
|
||||||
def current_context # :nodoc:
|
|
||||||
self.contexts.last
|
|
||||||
end
|
|
||||||
|
|
||||||
def add_context(context) # :nodoc:
|
|
||||||
self.contexts.push(context)
|
|
||||||
end
|
|
||||||
|
|
||||||
def remove_context # :nodoc:
|
|
||||||
self.contexts.pop
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
module ClassMethods
|
|
||||||
# == Should statements
|
|
||||||
#
|
|
||||||
# Should statements are just syntactic sugar over normal Test::Unit test
|
|
||||||
# methods. A should block contains all the normal code and assertions
|
|
||||||
# you're used to seeing, with the added benefit that they can be wrapped
|
|
||||||
# inside context blocks (see below).
|
|
||||||
#
|
|
||||||
# === Example:
|
|
||||||
#
|
|
||||||
# class UserTest < Test::Unit::TestCase
|
|
||||||
#
|
|
||||||
# def setup
|
|
||||||
# @user = User.new("John", "Doe")
|
|
||||||
# end
|
|
||||||
#
|
|
||||||
# should "return its full name"
|
|
||||||
# assert_equal 'John Doe', @user.full_name
|
|
||||||
# end
|
|
||||||
#
|
|
||||||
# end
|
|
||||||
#
|
|
||||||
# ...will produce the following test:
|
|
||||||
# * <tt>"test: User should return its full name. "</tt>
|
|
||||||
#
|
|
||||||
# Note: The part before <tt>should</tt> in the test name is gleamed from the name of the Test::Unit class.
|
|
||||||
#
|
|
||||||
# Should statements can also take a Proc as a <tt>:before </tt>option. This proc runs after any
|
|
||||||
# parent context's setups but before the current context's setup.
|
|
||||||
#
|
|
||||||
# === Example:
|
|
||||||
#
|
|
||||||
# context "Some context" do
|
|
||||||
# setup { puts("I run after the :before proc") }
|
|
||||||
#
|
|
||||||
# should "run a :before proc", :before => lambda { puts("I run before the setup") } do
|
|
||||||
# assert true
|
|
||||||
# end
|
|
||||||
# end
|
|
||||||
#
|
|
||||||
# Should statements can also wrap matchers, making virtually any matcher
|
|
||||||
# usable in a macro style. The matcher's description is used to generate a
|
|
||||||
# test name and failure message, and the test will pass if the matcher
|
|
||||||
# matches the subject.
|
|
||||||
#
|
|
||||||
# === Example:
|
|
||||||
#
|
|
||||||
# should validate_presence_of(:first_name).with_message(/gotta be there/)
|
|
||||||
#
|
|
||||||
|
|
||||||
def should(name_or_matcher, options = {}, &blk)
|
|
||||||
if Shoulda.current_context
|
|
||||||
Shoulda.current_context.should(name_or_matcher, options, &blk)
|
|
||||||
else
|
|
||||||
context_name = self.name.gsub(/Test/, "")
|
|
||||||
context = Shoulda::Context.new(context_name, self) do
|
|
||||||
should(name_or_matcher, options, &blk)
|
|
||||||
end
|
|
||||||
context.build
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# Allows negative tests using matchers. The matcher's description is used
|
|
||||||
# to generate a test name and negative failure message, and the test will
|
|
||||||
# pass unless the matcher matches the subject.
|
|
||||||
#
|
|
||||||
# === Example:
|
|
||||||
#
|
|
||||||
# should_not set_the_flash
|
|
||||||
def should_not(matcher)
|
|
||||||
if Shoulda.current_context
|
|
||||||
Shoulda.current_context.should_not(matcher)
|
|
||||||
else
|
|
||||||
context_name = self.name.gsub(/Test/, "")
|
|
||||||
context = Shoulda::Context.new(context_name, self) do
|
|
||||||
should_not(matcher)
|
|
||||||
end
|
|
||||||
context.build
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# == Before statements
|
|
||||||
#
|
|
||||||
# Before statements are should statements that run before the current
|
|
||||||
# context's setup. These are especially useful when setting expectations.
|
|
||||||
#
|
|
||||||
# === Example:
|
|
||||||
#
|
|
||||||
# class UserControllerTest < Test::Unit::TestCase
|
|
||||||
# context "the index action" do
|
|
||||||
# setup do
|
|
||||||
# @users = [Factory(:user)]
|
|
||||||
# User.stubs(:find).returns(@users)
|
|
||||||
# end
|
|
||||||
#
|
|
||||||
# context "on GET" do
|
|
||||||
# setup { get :index }
|
|
||||||
#
|
|
||||||
# should respond_with(:success)
|
|
||||||
#
|
|
||||||
# # runs before "get :index"
|
|
||||||
# before_should "find all users" do
|
|
||||||
# User.expects(:find).with(:all).returns(@users)
|
|
||||||
# end
|
|
||||||
# end
|
|
||||||
# end
|
|
||||||
# end
|
|
||||||
def before_should(name, &blk)
|
|
||||||
should(name, :before => blk) { assert true }
|
|
||||||
end
|
|
||||||
|
|
||||||
# Just like should, but never runs, and instead prints an 'X' in the Test::Unit output.
|
|
||||||
def should_eventually(name, options = {}, &blk)
|
|
||||||
context_name = self.name.gsub(/Test/, "")
|
|
||||||
context = Shoulda::Context.new(context_name, self) do
|
|
||||||
should_eventually(name, &blk)
|
|
||||||
end
|
|
||||||
context.build
|
|
||||||
end
|
|
||||||
|
|
||||||
# == Contexts
|
|
||||||
#
|
|
||||||
# A context block groups should statements under a common set of setup/teardown methods.
|
|
||||||
# Context blocks can be arbitrarily nested, and can do wonders for improving the maintainability
|
|
||||||
# and readability of your test code.
|
|
||||||
#
|
|
||||||
# A context block can contain setup, should, should_eventually, and teardown blocks.
|
|
||||||
#
|
|
||||||
# class UserTest < Test::Unit::TestCase
|
|
||||||
# context "A User instance" do
|
|
||||||
# setup do
|
|
||||||
# @user = User.find(:first)
|
|
||||||
# end
|
|
||||||
#
|
|
||||||
# should "return its full name"
|
|
||||||
# assert_equal 'John Doe', @user.full_name
|
|
||||||
# end
|
|
||||||
# end
|
|
||||||
# end
|
|
||||||
#
|
|
||||||
# This code will produce the method <tt>"test: A User instance should return its full name. "</tt>.
|
|
||||||
#
|
|
||||||
# Contexts may be nested. Nested contexts run their setup blocks from out to in before each
|
|
||||||
# should statement. They then run their teardown blocks from in to out after each should statement.
|
|
||||||
#
|
|
||||||
# class UserTest < Test::Unit::TestCase
|
|
||||||
# context "A User instance" do
|
|
||||||
# setup do
|
|
||||||
# @user = User.find(:first)
|
|
||||||
# end
|
|
||||||
#
|
|
||||||
# should "return its full name"
|
|
||||||
# assert_equal 'John Doe', @user.full_name
|
|
||||||
# end
|
|
||||||
#
|
|
||||||
# context "with a profile" do
|
|
||||||
# setup do
|
|
||||||
# @user.profile = Profile.find(:first)
|
|
||||||
# end
|
|
||||||
#
|
|
||||||
# should "return true when sent :has_profile?"
|
|
||||||
# assert @user.has_profile?
|
|
||||||
# end
|
|
||||||
# end
|
|
||||||
# end
|
|
||||||
# end
|
|
||||||
#
|
|
||||||
# This code will produce the following methods
|
|
||||||
# * <tt>"test: A User instance should return its full name. "</tt>
|
|
||||||
# * <tt>"test: A User instance with a profile should return true when sent :has_profile?. "</tt>
|
|
||||||
#
|
|
||||||
# <b>Just like should statements, a context block can exist next to normal <tt>def test_the_old_way; end</tt>
|
|
||||||
# tests</b>. This means you do not have to fully commit to the context/should syntax in a test file.
|
|
||||||
|
|
||||||
def context(name, &blk)
|
|
||||||
if Shoulda.current_context
|
|
||||||
Shoulda.current_context.context(name, &blk)
|
|
||||||
else
|
|
||||||
context = Shoulda::Context.new(name, self, &blk)
|
|
||||||
context.build
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# Returns the class being tested, as determined by the test class name.
|
|
||||||
#
|
|
||||||
# class UserTest; described_type; end
|
|
||||||
# # => User
|
|
||||||
def described_type
|
|
||||||
self.name.gsub(/Test$/, '').constantize
|
|
||||||
end
|
|
||||||
|
|
||||||
# Sets the return value of the subject instance method:
|
|
||||||
#
|
|
||||||
# class UserTest < Test::Unit::TestCase
|
|
||||||
# subject { User.first }
|
|
||||||
#
|
|
||||||
# # uses the existing user
|
|
||||||
# should validate_uniqueness_of(:email)
|
|
||||||
# end
|
|
||||||
def subject(&block)
|
|
||||||
@subject_block = block
|
|
||||||
end
|
|
||||||
|
|
||||||
def subject_block # :nodoc:
|
|
||||||
@subject_block
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
module InstanceMethods
|
|
||||||
# Returns an instance of the class under test.
|
|
||||||
#
|
|
||||||
# class UserTest
|
|
||||||
# should "be a user" do
|
|
||||||
# assert_kind_of User, subject # passes
|
|
||||||
# end
|
|
||||||
# end
|
|
||||||
#
|
|
||||||
# The subject can be explicitly set using the subject class method:
|
|
||||||
#
|
|
||||||
# class UserTest
|
|
||||||
# subject { User.first }
|
|
||||||
# should "be an existing user" do
|
|
||||||
# assert !subject.new_record? # uses the first user
|
|
||||||
# end
|
|
||||||
# end
|
|
||||||
#
|
|
||||||
# The subject is used by all macros that require an instance of the class
|
|
||||||
# being tested.
|
|
||||||
def subject
|
|
||||||
@shoulda_subject ||= construct_subject
|
|
||||||
end
|
|
||||||
|
|
||||||
def subject_block # :nodoc:
|
|
||||||
(@shoulda_context && @shoulda_context.subject_block) || self.class.subject_block
|
|
||||||
end
|
|
||||||
|
|
||||||
def get_instance_of(object_or_klass) # :nodoc:
|
|
||||||
if object_or_klass.is_a?(Class)
|
|
||||||
object_or_klass.new
|
|
||||||
else
|
|
||||||
object_or_klass
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def instance_variable_name_for(klass) # :nodoc:
|
|
||||||
klass.to_s.split('::').last.underscore
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def construct_subject
|
|
||||||
if subject_block
|
|
||||||
instance_eval(&subject_block)
|
|
||||||
else
|
|
||||||
get_instance_of(self.class.described_type)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
class Context # :nodoc:
|
|
||||||
|
|
||||||
attr_accessor :name # my name
|
|
||||||
attr_accessor :parent # may be another context, or the original test::unit class.
|
|
||||||
attr_accessor :subcontexts # array of contexts nested under myself
|
|
||||||
attr_accessor :setup_blocks # blocks given via setup methods
|
|
||||||
attr_accessor :teardown_blocks # blocks given via teardown methods
|
|
||||||
attr_accessor :shoulds # array of hashes representing the should statements
|
|
||||||
attr_accessor :should_eventuallys # array of hashes representing the should eventually statements
|
|
||||||
attr_accessor :subject_block
|
|
||||||
|
|
||||||
def initialize(name, parent, &blk)
|
|
||||||
Shoulda.add_context(self)
|
|
||||||
self.name = name
|
|
||||||
self.parent = parent
|
|
||||||
self.setup_blocks = []
|
|
||||||
self.teardown_blocks = []
|
|
||||||
self.shoulds = []
|
|
||||||
self.should_eventuallys = []
|
|
||||||
self.subcontexts = []
|
|
||||||
|
|
||||||
merge_block(&blk)
|
|
||||||
Shoulda.remove_context
|
|
||||||
end
|
|
||||||
|
|
||||||
def merge_block(&blk)
|
|
||||||
blk.bind(self).call
|
|
||||||
end
|
|
||||||
|
|
||||||
def context(name, &blk)
|
|
||||||
self.subcontexts << Context.new(name, self, &blk)
|
|
||||||
end
|
|
||||||
|
|
||||||
def setup(&blk)
|
|
||||||
self.setup_blocks << blk
|
|
||||||
end
|
|
||||||
|
|
||||||
def teardown(&blk)
|
|
||||||
self.teardown_blocks << blk
|
|
||||||
end
|
|
||||||
|
|
||||||
def should(name_or_matcher, options = {}, &blk)
|
|
||||||
if name_or_matcher.respond_to?(:description) && name_or_matcher.respond_to?(:matches?)
|
|
||||||
name = name_or_matcher.description
|
|
||||||
blk = lambda { assert_accepts name_or_matcher, subject }
|
|
||||||
else
|
|
||||||
name = name_or_matcher
|
|
||||||
end
|
|
||||||
|
|
||||||
if blk
|
|
||||||
self.shoulds << { :name => name, :before => options[:before], :block => blk }
|
|
||||||
else
|
|
||||||
self.should_eventuallys << { :name => name }
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def should_not(matcher)
|
|
||||||
name = matcher.description
|
|
||||||
blk = lambda { assert_rejects matcher, subject }
|
|
||||||
self.shoulds << { :name => "not #{name}", :block => blk }
|
|
||||||
end
|
|
||||||
|
|
||||||
def should_eventually(name, &blk)
|
|
||||||
self.should_eventuallys << { :name => name, :block => blk }
|
|
||||||
end
|
|
||||||
|
|
||||||
def subject(&block)
|
|
||||||
self.subject_block = block
|
|
||||||
end
|
|
||||||
|
|
||||||
def subject_block
|
|
||||||
return @subject_block if @subject_block
|
|
||||||
parent.subject_block
|
|
||||||
end
|
|
||||||
|
|
||||||
def full_name
|
|
||||||
parent_name = parent.full_name if am_subcontext?
|
|
||||||
return [parent_name, name].join(" ").strip
|
|
||||||
end
|
|
||||||
|
|
||||||
def am_subcontext?
|
|
||||||
parent.is_a?(self.class) # my parent is the same class as myself.
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_unit_class
|
|
||||||
am_subcontext? ? parent.test_unit_class : parent
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_methods
|
|
||||||
@test_methods ||= Hash.new { |h,k|
|
|
||||||
h[k] = Hash[k.instance_methods.map { |n| [n, true] }]
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
def create_test_from_should_hash(should)
|
|
||||||
test_name = ["test:", full_name, "should", "#{should[:name]}. "].flatten.join(' ').to_sym
|
|
||||||
|
|
||||||
if test_methods[test_unit_class][test_name.to_s] then
|
|
||||||
warn " * WARNING: '#{test_name}' is already defined"
|
|
||||||
end
|
|
||||||
|
|
||||||
test_methods[test_unit_class][test_name.to_s] = true
|
|
||||||
|
|
||||||
context = self
|
|
||||||
test_unit_class.send(:define_method, test_name) do
|
|
||||||
@shoulda_context = context
|
|
||||||
begin
|
|
||||||
context.run_parent_setup_blocks(self)
|
|
||||||
should[:before].bind(self).call if should[:before]
|
|
||||||
context.run_current_setup_blocks(self)
|
|
||||||
should[:block].bind(self).call
|
|
||||||
ensure
|
|
||||||
context.run_all_teardown_blocks(self)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def run_all_setup_blocks(binding)
|
|
||||||
run_parent_setup_blocks(binding)
|
|
||||||
run_current_setup_blocks(binding)
|
|
||||||
end
|
|
||||||
|
|
||||||
def run_parent_setup_blocks(binding)
|
|
||||||
self.parent.run_all_setup_blocks(binding) if am_subcontext?
|
|
||||||
end
|
|
||||||
|
|
||||||
def run_current_setup_blocks(binding)
|
|
||||||
setup_blocks.each do |setup_block|
|
|
||||||
setup_block.bind(binding).call
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def run_all_teardown_blocks(binding)
|
|
||||||
teardown_blocks.reverse.each do |teardown_block|
|
|
||||||
teardown_block.bind(binding).call
|
|
||||||
end
|
|
||||||
self.parent.run_all_teardown_blocks(binding) if am_subcontext?
|
|
||||||
end
|
|
||||||
|
|
||||||
def print_should_eventuallys
|
|
||||||
should_eventuallys.each do |should|
|
|
||||||
test_name = [full_name, "should", "#{should[:name]}. "].flatten.join(' ')
|
|
||||||
puts " * DEFERRED: " + test_name
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def build
|
|
||||||
shoulds.each do |should|
|
|
||||||
create_test_from_should_hash(should)
|
|
||||||
end
|
|
||||||
|
|
||||||
subcontexts.each { |context| context.build }
|
|
||||||
|
|
||||||
print_should_eventuallys
|
|
||||||
end
|
|
||||||
|
|
||||||
def method_missing(method, *args, &blk)
|
|
||||||
test_unit_class.send(method, *args, &blk)
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,22 +1,23 @@
|
||||||
require 'shoulda/active_record/matchers'
|
|
||||||
require 'shoulda/action_controller/matchers'
|
|
||||||
require 'shoulda/action_mailer/matchers'
|
|
||||||
|
|
||||||
# :enddoc:
|
# :enddoc:
|
||||||
|
|
||||||
module RSpec
|
if defined?(::ActiveRecord)
|
||||||
module Matchers
|
require 'shoulda/active_record'
|
||||||
|
module RSpec::Matchers
|
||||||
include Shoulda::ActiveRecord::Matchers
|
include Shoulda::ActiveRecord::Matchers
|
||||||
end
|
end
|
||||||
|
end
|
||||||
module Rails
|
|
||||||
module ControllerExampleGroup
|
if defined?(::ActionController)
|
||||||
include Shoulda::ActionController::Matchers
|
require 'shoulda/action_controller'
|
||||||
end
|
module Rails::ControllerExampleGroup
|
||||||
|
include Shoulda::ActionController::Matchers
|
||||||
module MailerExampleGroup
|
end
|
||||||
include Shoulda::ActionMailer::Matchers
|
end
|
||||||
end
|
|
||||||
end
|
if defined?(::ActionMailer)
|
||||||
|
require 'shoulda/action_mailer'
|
||||||
|
module Rails::MailerExampleGroup
|
||||||
|
include Shoulda::ActionMailer::Matchers
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -1,17 +1,40 @@
|
||||||
require 'test/unit'
|
# :enddoc:
|
||||||
|
|
||||||
require 'shoulda/context'
|
if defined?(ActionController)
|
||||||
require 'shoulda/proc_extensions'
|
require 'shoulda/action_controller'
|
||||||
require 'shoulda/assertions'
|
|
||||||
require 'shoulda/autoload_macros'
|
|
||||||
require 'shoulda/rails' if defined? RAILS_ROOT
|
|
||||||
|
|
||||||
module Test # :nodoc: all
|
class ActionController::TestCase
|
||||||
module Unit
|
include Shoulda::ActionController::Matchers
|
||||||
class TestCase
|
extend Shoulda::ActionController::Matchers
|
||||||
include Shoulda::InstanceMethods
|
|
||||||
extend Shoulda::ClassMethods
|
def subject
|
||||||
include Shoulda::Assertions
|
@controller
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if defined?(ActionMailer)
|
||||||
|
require 'shoulda/action_mailer'
|
||||||
|
|
||||||
|
module Test
|
||||||
|
module Unit
|
||||||
|
class TestCase
|
||||||
|
include Shoulda::ActionMailer::Matchers
|
||||||
|
extend Shoulda::ActionMailer::Matchers
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if defined?(ActiveRecord)
|
||||||
|
require 'shoulda/active_record'
|
||||||
|
|
||||||
|
module Test
|
||||||
|
module Unit
|
||||||
|
class TestCase
|
||||||
|
include Shoulda::ActiveRecord::Matchers
|
||||||
|
extend Shoulda::ActiveRecord::Matchers
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,14 +0,0 @@
|
||||||
# Stolen straight from ActiveSupport
|
|
||||||
|
|
||||||
class Proc #:nodoc:
|
|
||||||
def bind(object)
|
|
||||||
block, time = self, Time.now
|
|
||||||
(class << object; self end).class_eval do
|
|
||||||
method_name = "__bind_#{time.to_i}_#{time.usec}"
|
|
||||||
define_method(method_name, &block)
|
|
||||||
method = instance_method(method_name)
|
|
||||||
remove_method(method_name)
|
|
||||||
method
|
|
||||||
end.bind(object)
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,8 +0,0 @@
|
||||||
require 'rubygems'
|
|
||||||
require 'active_support'
|
|
||||||
require 'shoulda'
|
|
||||||
|
|
||||||
require 'shoulda/active_record' if defined? ActiveRecord::Base
|
|
||||||
require 'shoulda/action_controller' if defined? ActionController::Base
|
|
||||||
require 'shoulda/action_mailer' if defined? ActionMailer::Base
|
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
Dir[File.join(File.dirname(__FILE__), 'tasks', '*.rake')].each do |f|
|
|
||||||
load f
|
|
||||||
end
|
|
|
@ -1,29 +0,0 @@
|
||||||
namespace :shoulda do
|
|
||||||
desc "List the names of the test methods in a specification like format"
|
|
||||||
task :list do
|
|
||||||
$LOAD_PATH.unshift("test")
|
|
||||||
|
|
||||||
require 'test/unit'
|
|
||||||
require 'rubygems'
|
|
||||||
require 'active_support'
|
|
||||||
|
|
||||||
# bug in test unit. Set to true to stop from running.
|
|
||||||
Test::Unit.run = true
|
|
||||||
|
|
||||||
test_files = Dir.glob(File.join('test', '**', '*_test.rb'))
|
|
||||||
test_files.each do |file|
|
|
||||||
load file
|
|
||||||
klass = File.basename(file, '.rb').classify
|
|
||||||
unless Object.const_defined?(klass.to_s)
|
|
||||||
puts "Skipping #{klass} because it doesn't map to a Class"
|
|
||||||
next
|
|
||||||
end
|
|
||||||
klass = klass.constantize
|
|
||||||
|
|
||||||
puts klass.name.gsub('Test', '')
|
|
||||||
|
|
||||||
test_methods = klass.instance_methods.grep(/^test/).map {|s| s.gsub(/^test: /, '')}.sort
|
|
||||||
test_methods.each {|m| puts " " + m }
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,28 +0,0 @@
|
||||||
namespace :shoulda do
|
|
||||||
# From http://blog.internautdesign.com/2007/11/2/a-yaml_to_shoulda-rake-task
|
|
||||||
# David.Lowenfels@gmail.com
|
|
||||||
desc "Converts a YAML file (FILE=./path/to/yaml) into a Shoulda skeleton"
|
|
||||||
task :from_yaml do
|
|
||||||
require 'yaml'
|
|
||||||
|
|
||||||
def yaml_to_context(hash, indent = 0)
|
|
||||||
indent1 = ' ' * indent
|
|
||||||
indent2 = ' ' * (indent + 1)
|
|
||||||
hash.each_pair do |context, shoulds|
|
|
||||||
puts indent1 + "context \"#{context}\" do"
|
|
||||||
puts
|
|
||||||
shoulds.each do |should|
|
|
||||||
yaml_to_context( should, indent + 1 ) and next if should.is_a?( Hash )
|
|
||||||
puts indent2 + "should_eventually \"" + should.gsub(/^should +/,'') + "\" do"
|
|
||||||
puts indent2 + "end"
|
|
||||||
puts
|
|
||||||
end
|
|
||||||
puts indent1 + "end"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
puts("Please pass in a FILE argument.") and exit unless ENV['FILE']
|
|
||||||
|
|
||||||
yaml_to_context( YAML.load_file( ENV['FILE'] ) )
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,8 +0,0 @@
|
||||||
if RAILS_ENV == 'test'
|
|
||||||
if defined? Spec
|
|
||||||
require 'shoulda/integrations/rspec'
|
|
||||||
else
|
|
||||||
require 'shoulda/integrations/test_unit'
|
|
||||||
Shoulda.autoload_macros RAILS_ROOT, File.join("vendor", "{plugins,gems}", "*")
|
|
||||||
end
|
|
||||||
end
|
|
7
spec/rails3_root/Gemfile
Normal file
7
spec/rails3_root/Gemfile
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
source 'http://rubygems.org'
|
||||||
|
|
||||||
|
gem 'rails', '3.0.0.beta4'
|
||||||
|
gem 'sqlite3-ruby', :require => 'sqlite3'
|
||||||
|
gem 'mocha'
|
||||||
|
gem 'rspec-rails', '2.0.0.beta.12'
|
||||||
|
|
|
@ -31,6 +31,7 @@ GEM
|
||||||
arel (0.4.0)
|
arel (0.4.0)
|
||||||
activesupport (>= 3.0.0.beta)
|
activesupport (>= 3.0.0.beta)
|
||||||
builder (2.1.2)
|
builder (2.1.2)
|
||||||
|
diff-lcs (1.1.2)
|
||||||
erubis (2.6.6)
|
erubis (2.6.6)
|
||||||
abstract (>= 1.0.0)
|
abstract (>= 1.0.0)
|
||||||
i18n (0.4.1)
|
i18n (0.4.1)
|
||||||
|
@ -42,6 +43,7 @@ GEM
|
||||||
mime-types (1.16)
|
mime-types (1.16)
|
||||||
mocha (0.9.10)
|
mocha (0.9.10)
|
||||||
rake
|
rake
|
||||||
|
nokogiri (1.4.4)
|
||||||
polyglot (0.3.1)
|
polyglot (0.3.1)
|
||||||
rack (1.1.0)
|
rack (1.1.0)
|
||||||
rack-mount (0.6.13)
|
rack-mount (0.6.13)
|
||||||
|
@ -62,11 +64,26 @@ GEM
|
||||||
rake (>= 0.8.3)
|
rake (>= 0.8.3)
|
||||||
thor (~> 0.13.6)
|
thor (~> 0.13.6)
|
||||||
rake (0.8.7)
|
rake (0.8.7)
|
||||||
|
rspec (2.0.0.beta.12)
|
||||||
|
rspec-core (= 2.0.0.beta.12)
|
||||||
|
rspec-expectations (= 2.0.0.beta.12)
|
||||||
|
rspec-mocks (= 2.0.0.beta.12)
|
||||||
|
rspec-core (2.0.0.beta.12)
|
||||||
|
rspec-expectations (2.0.0.beta.12)
|
||||||
|
diff-lcs (>= 1.1.2)
|
||||||
|
rspec-mocks (2.0.0.beta.12)
|
||||||
|
rspec-rails (2.0.0.beta.12)
|
||||||
|
rspec (= 2.0.0.beta.12)
|
||||||
|
webrat (>= 0.7.0)
|
||||||
sqlite3-ruby (1.3.2)
|
sqlite3-ruby (1.3.2)
|
||||||
thor (0.13.8)
|
thor (0.13.8)
|
||||||
treetop (1.4.9)
|
treetop (1.4.9)
|
||||||
polyglot (>= 0.3.1)
|
polyglot (>= 0.3.1)
|
||||||
tzinfo (0.3.23)
|
tzinfo (0.3.23)
|
||||||
|
webrat (0.7.2)
|
||||||
|
nokogiri (>= 1.2.0)
|
||||||
|
rack (>= 1.0)
|
||||||
|
rack-test (>= 0.5.3)
|
||||||
|
|
||||||
PLATFORMS
|
PLATFORMS
|
||||||
ruby
|
ruby
|
||||||
|
@ -74,4 +91,5 @@ PLATFORMS
|
||||||
DEPENDENCIES
|
DEPENDENCIES
|
||||||
mocha
|
mocha
|
||||||
rails (= 3.0.0.beta4)
|
rails (= 3.0.0.beta4)
|
||||||
|
rspec-rails (= 2.0.0.beta.12)
|
||||||
sqlite3-ruby
|
sqlite3-ruby
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue