Permalink
Browse files

Removed all ThoughtBot (and Thoughtbot) namespaces

  • Loading branch information...
1 parent 5ede009 commit 5c1329f6b9068c879d3d3182610b992c64ba2519 @webmat webmat committed Jan 5, 2009
View
8 README.rdoc
@@ -10,7 +10,7 @@ Assertions:: Many common rails testing idioms have been distilled into a set of
= Usage
-=== Context Helpers (ThoughtBot::Shoulda::Context)
+=== Context Helpers (Shoulda::Context)
Stop killing your fingers with all of those underscores... Name your tests with plain sentences!
@@ -43,7 +43,7 @@ Produces the following test methods:
So readable!
-=== ActiveRecord Tests (ThoughtBot::Shoulda::ActiveRecord::Macros)
+=== ActiveRecord Tests (Shoulda::ActiveRecord::Macros)
Quick macro tests for your ActiveRecord associations and validations:
@@ -71,7 +71,7 @@ Quick macro tests for your ActiveRecord associations and validations:
Makes TDD so much easier.
-=== Controller Tests (ThoughtBot::Shoulda::Controller::Macros)
+=== Controller Tests (Shoulda::Controller::Macros)
Macros to test the most common controller patterns...
@@ -90,7 +90,7 @@ Macros to test the most common controller patterns...
end
end
-=== Helpful Assertions (ThoughtBot::Shoulda::Assertions)
+=== Helpful Assertions (Shoulda::Assertions)
More to come here, but have fun with what's there.
View
2 Rakefile
@@ -38,7 +38,7 @@ task :default => ['test']
spec = Gem::Specification.new do |s|
s.name = "shoulda"
- s.version = Thoughtbot::Shoulda::VERSION
+ s.version = Shoulda::VERSION
s.summary = "Making tests easy on the fingers and eyes"
s.homepage = "http://thoughtbot.com/projects/shoulda"
s.rubyforge_project = "shoulda"
View
8 lib/shoulda.rb
@@ -8,10 +8,10 @@
module Test # :nodoc: all
module Unit
class TestCase
- extend Thoughtbot::Shoulda
- include ThoughtBot::Shoulda::Assertions
- extend ThoughtBot::Shoulda::Macros
- include ThoughtBot::Shoulda::Helpers
+ extend Shoulda
+ include Shoulda::Assertions
+ extend Shoulda::Macros
+ include Shoulda::Helpers
end
end
end
View
2 lib/shoulda/action_mailer.rb
@@ -4,7 +4,7 @@
module Test # :nodoc: all
module Unit
class TestCase
- include ThoughtBot::Shoulda::ActionMailer::Assertions
+ include Shoulda::ActionMailer::Assertions
end
end
end
View
65 lib/shoulda/action_mailer/assertions.rb
@@ -1,39 +1,38 @@
-module ThoughtBot # :nodoc:
- module Shoulda # :nodoc:
- module ActionMailer # :nodoc:
- module Assertions
- # Asserts that an email was delivered. Can take a block that can further
- # narrow down the types of emails you're expecting.
- #
- # assert_sent_email
- #
- # Passes if ActionMailer::Base.deliveries has an email
- #
- # assert_sent_email do |email|
- # email.subject =~ /hi there/ && email.to.include?('none@none.com')
- # end
- #
- # Passes if there is an email with subject containing 'hi there' and
- # 'none@none.com' as one of the recipients.
- #
- def assert_sent_email
- emails = ::ActionMailer::Base.deliveries
- assert !emails.empty?, "No emails were sent"
- if block_given?
- matching_emails = emails.select {|email| yield email }
- assert !matching_emails.empty?, "None of the emails matched."
- end
+module Shoulda # :nodoc:
+ module ActionMailer # :nodoc:
+ module Assertions
+ # Asserts that an email was delivered. Can take a block that can further
+ # narrow down the types of emails you're expecting.
+ #
+ # assert_sent_email
+ #
+ # Passes if ActionMailer::Base.deliveries has an email
+ #
+ # assert_sent_email do |email|
+ # email.subject =~ /hi there/ && email.to.include?('none@none.com')
+ # end
+ #
+ # Passes if there is an email with subject containing 'hi there' and
+ # 'none@none.com' as one of the recipients.
+ #
+ def assert_sent_email
+ emails = ::ActionMailer::Base.deliveries
+ assert !emails.empty?, "No emails were sent"
+ if block_given?
+ matching_emails = emails.select {|email| yield email }
+ assert !matching_emails.empty?, "None of the emails matched."
end
+ end
- # Asserts that no ActionMailer mails were delivered
- #
- # assert_did_not_send_email
- def assert_did_not_send_email
- msg = "Sent #{::ActionMailer::Base.deliveries.size} emails.\n"
- ::ActionMailer::Base.deliveries.each { |m| msg << " '#{m.subject}' sent to #{m.to.to_sentence}\n" }
- assert ::ActionMailer::Base.deliveries.empty?, msg
- end
+ # Asserts that no ActionMailer mails were delivered
+ #
+ # assert_did_not_send_email
+ def assert_did_not_send_email
+ msg = "Sent #{::ActionMailer::Base.deliveries.size} emails.\n"
+ ::ActionMailer::Base.deliveries.each { |m| msg << " '#{m.subject}' sent to #{m.to.to_sentence}\n" }
+ assert ::ActionMailer::Base.deliveries.empty?, msg
end
end
end
end
+
View
4 lib/shoulda/active_record.rb
@@ -5,8 +5,8 @@
module Test # :nodoc: all
module Unit
class TestCase
- include ThoughtBot::Shoulda::ActiveRecord::Assertions
- extend ThoughtBot::Shoulda::ActiveRecord::Macros
+ include Shoulda::ActiveRecord::Assertions
+ extend Shoulda::ActiveRecord::Macros
end
end
end
View
150 lib/shoulda/active_record/assertions.rb
@@ -1,86 +1,84 @@
-module ThoughtBot # :nodoc:
- module Shoulda # :nodoc:
- module ActiveRecord # :nodoc:
- module Assertions
- # Asserts that the given object can be saved
- #
- # assert_save User.new(params)
- def assert_save(obj)
- assert obj.save, "Errors: #{pretty_error_messages obj}"
- obj.reload
- end
+module Shoulda # :nodoc:
+ module ActiveRecord # :nodoc:
+ module Assertions
+ # Asserts that the given object can be saved
+ #
+ # assert_save User.new(params)
+ def assert_save(obj)
+ assert obj.save, "Errors: #{pretty_error_messages obj}"
+ obj.reload
+ end
- # Asserts that the given object is valid
- #
- # assert_valid User.new(params)
- def assert_valid(obj)
- assert obj.valid?, "Errors: #{pretty_error_messages obj}"
- end
+ # Asserts that the given object is valid
+ #
+ # assert_valid User.new(params)
+ def assert_valid(obj)
+ assert obj.valid?, "Errors: #{pretty_error_messages obj}"
+ end
- # Asserts that an Active Record model validates with the passed
- # <tt>value</tt> by making sure the <tt>error_message_to_avoid</tt> is not
- # contained within the list of errors for that attribute.
- #
- # assert_good_value(User.new, :email, "user@example.com")
- # assert_good_value(User.new, :ssn, "123456789", /length/)
- #
- # If a class is passed as the first argument, a new object will be
- # instantiated before the assertion. If an instance variable exists with
- # the same name as the class (underscored), that object will be used
- # instead.
- #
- # assert_good_value(User, :email, "user@example.com")
- #
- # @product = Product.new(:tangible => false)
- # assert_good_value(Product, :price, "0")
- def assert_good_value(object_or_klass, attribute, value, error_message_to_avoid = //)
- object = get_instance_of(object_or_klass)
- object.send("#{attribute}=", value)
- object.valid?
- assert_does_not_contain(object.errors.on(attribute), error_message_to_avoid, "when set to #{value.inspect}")
- end
+ # Asserts that an Active Record model validates with the passed
+ # <tt>value</tt> by making sure the <tt>error_message_to_avoid</tt> is not
+ # contained within the list of errors for that attribute.
+ #
+ # assert_good_value(User.new, :email, "user@example.com")
+ # assert_good_value(User.new, :ssn, "123456789", /length/)
+ #
+ # If a class is passed as the first argument, a new object will be
+ # instantiated before the assertion. If an instance variable exists with
+ # the same name as the class (underscored), that object will be used
+ # instead.
+ #
+ # assert_good_value(User, :email, "user@example.com")
+ #
+ # @product = Product.new(:tangible => false)
+ # assert_good_value(Product, :price, "0")
+ def assert_good_value(object_or_klass, attribute, value, error_message_to_avoid = //)
+ object = get_instance_of(object_or_klass)
+ object.send("#{attribute}=", value)
+ object.valid?
+ assert_does_not_contain(object.errors.on(attribute), error_message_to_avoid, "when set to #{value.inspect}")
+ end
- # Asserts that an Active Record model invalidates the passed
- # <tt>value</tt> by making sure the <tt>error_message_to_expect</tt> is
- # contained within the list of errors for that attribute.
- #
- # assert_bad_value(User.new, :email, "invalid")
- # assert_bad_value(User.new, :ssn, "123", /length/)
- #
- # If a class is passed as the first argument, a new object will be
- # instantiated before the assertion. If an instance variable exists with
- # the same name as the class (underscored), that object will be used
- # instead.
- #
- # assert_bad_value(User, :email, "invalid")
- #
- # @product = Product.new(:tangible => true)
- # assert_bad_value(Product, :price, "0")
- def assert_bad_value(object_or_klass, attribute, value,
- error_message_to_expect = self.class.default_error_message(:invalid))
- object = get_instance_of(object_or_klass)
- object.send("#{attribute}=", value)
- assert !object.valid?, "#{object.class} allowed #{value.inspect} as a value for #{attribute}"
- assert object.errors.on(attribute), "There are no errors on #{attribute} after being set to #{value.inspect}"
- assert_contains(object.errors.on(attribute), error_message_to_expect, "when set to #{value.inspect}")
- end
+ # Asserts that an Active Record model invalidates the passed
+ # <tt>value</tt> by making sure the <tt>error_message_to_expect</tt> is
+ # contained within the list of errors for that attribute.
+ #
+ # assert_bad_value(User.new, :email, "invalid")
+ # assert_bad_value(User.new, :ssn, "123", /length/)
+ #
+ # If a class is passed as the first argument, a new object will be
+ # instantiated before the assertion. If an instance variable exists with
+ # the same name as the class (underscored), that object will be used
+ # instead.
+ #
+ # assert_bad_value(User, :email, "invalid")
+ #
+ # @product = Product.new(:tangible => true)
+ # assert_bad_value(Product, :price, "0")
+ def assert_bad_value(object_or_klass, attribute, value,
+ error_message_to_expect = self.class.default_error_message(:invalid))
+ object = get_instance_of(object_or_klass)
+ object.send("#{attribute}=", value)
+ assert !object.valid?, "#{object.class} allowed #{value.inspect} as a value for #{attribute}"
+ assert object.errors.on(attribute), "There are no errors on #{attribute} after being set to #{value.inspect}"
+ assert_contains(object.errors.on(attribute), error_message_to_expect, "when set to #{value.inspect}")
+ end
- def pretty_error_messages(obj)
- obj.errors.map do |a, m|
- msg = "#{a} #{m}"
- msg << " (#{obj.send(a).inspect})" unless a.to_sym == :base
- end
+ def pretty_error_messages(obj)
+ obj.errors.map do |a, m|
+ msg = "#{a} #{m}"
+ msg << " (#{obj.send(a).inspect})" unless a.to_sym == :base
end
+ end
- private
+ private
- def get_instance_of(object_or_klass)
- if object_or_klass.is_a?(Class)
- klass = object_or_klass
- instance_variable_get("@#{klass.to_s.underscore}") || klass.new
- else
- object_or_klass
- end
+ def get_instance_of(object_or_klass)
+ if object_or_klass.is_a?(Class)
+ klass = object_or_klass
+ instance_variable_get("@#{klass.to_s.underscore}") || klass.new
+ else
+ object_or_klass
end
end
end
View
1,210 lib/shoulda/active_record/macros.rb
@@ -1,711 +1,709 @@
-module ThoughtBot # :nodoc:
- module Shoulda # :nodoc:
- module ActiveRecord # :nodoc:
- module MacroHelpers # :nodoc:
- # Helper method that determines the default error message used by Active
- # Record. Works for both existing Rails 2.1 and Rails 2.2 with the newly
- # introduced I18n module used for localization.
- #
- # default_error_message(:blank)
- # default_error_message(:too_short, :count => 5)
- # default_error_message(:too_long, :count => 60)
- def default_error_message(key, values = {})
- if Object.const_defined?(:I18n) # Rails >= 2.2
- I18n.translate("activerecord.errors.messages.#{key}", values)
- else # Rails <= 2.1.x
- ::ActiveRecord::Errors.default_error_messages[key] % values[:count]
- end
+module Shoulda # :nodoc:
+ module ActiveRecord # :nodoc:
+ module MacroHelpers # :nodoc:
+ # Helper method that determines the default error message used by Active
+ # Record. Works for both existing Rails 2.1 and Rails 2.2 with the newly
+ # introduced I18n module used for localization.
+ #
+ # default_error_message(:blank)
+ # default_error_message(:too_short, :count => 5)
+ # default_error_message(:too_long, :count => 60)
+ def default_error_message(key, values = {})
+ if Object.const_defined?(:I18n) # Rails >= 2.2
+ I18n.translate("activerecord.errors.messages.#{key}", values)
+ else # Rails <= 2.1.x
+ ::ActiveRecord::Errors.default_error_messages[key] % values[:count]
end
end
+ end
- # = Macro test helpers for your active record models
+ # = Macro test helpers for your active record models
+ #
+ # These helpers will test most of the validations and associations for your ActiveRecord models.
+ #
+ # class UserTest < Test::Unit::TestCase
+ # should_require_attributes :name, :phone_number
+ # should_not_allow_values_for :phone_number, "abcd", "1234"
+ # should_allow_values_for :phone_number, "(123) 456-7890"
+ #
+ # should_protect_attributes :password
+ #
+ # should_have_one :profile
+ # should_have_many :dogs
+ # should_have_many :messes, :through => :dogs
+ # should_belong_to :lover
+ # end
+ #
+ # For all of these helpers, the last parameter may be a hash of options.
+ #
+ module Macros
+ include MacroHelpers
+
+ # <b>DEPRECATED:</b> Use <tt>fixtures :all</tt> instead
#
- # These helpers will test most of the validations and associations for your ActiveRecord models.
+ # Loads all fixture files (<tt>test/fixtures/*.yml</tt>)
+ def load_all_fixtures
+ warn "[DEPRECATION] load_all_fixtures is deprecated. Use `fixtures :all` instead."
+ fixtures :all
+ end
+
+ # Ensures that the model cannot be saved if one of the attributes listed is not present.
#
- # class UserTest < Test::Unit::TestCase
- # should_require_attributes :name, :phone_number
- # should_not_allow_values_for :phone_number, "abcd", "1234"
- # should_allow_values_for :phone_number, "(123) 456-7890"
+ # If an instance variable has been created in the setup named after the
+ # model being tested, then this method will use that. Otherwise, it will
+ # create a new instance to test against.
#
- # should_protect_attributes :password
+ # Options:
+ # * <tt>:message</tt> - value the test expects to find in <tt>errors.on(:attribute)</tt>.
+ # Regexp or string. Default = <tt>I18n.translate('activerecord.errors.messages.blank')</tt>
#
- # should_have_one :profile
- # should_have_many :dogs
- # should_have_many :messes, :through => :dogs
- # should_belong_to :lover
- # end
+ # Example:
+ # should_require_attributes :name, :phone_number
#
- # For all of these helpers, the last parameter may be a hash of options.
- #
- module Macros
- include MacroHelpers
-
- # <b>DEPRECATED:</b> Use <tt>fixtures :all</tt> instead
- #
- # Loads all fixture files (<tt>test/fixtures/*.yml</tt>)
- def load_all_fixtures
- warn "[DEPRECATION] load_all_fixtures is deprecated. Use `fixtures :all` instead."
- fixtures :all
- end
-
- # Ensures that the model cannot be saved if one of the attributes listed is not present.
- #
- # If an instance variable has been created in the setup named after the
- # model being tested, then this method will use that. Otherwise, it will
- # create a new instance to test against.
- #
- # Options:
- # * <tt>:message</tt> - value the test expects to find in <tt>errors.on(:attribute)</tt>.
- # Regexp or string. Default = <tt>I18n.translate('activerecord.errors.messages.blank')</tt>
- #
- # Example:
- # should_require_attributes :name, :phone_number
- #
- def should_require_attributes(*attributes)
- message = get_options!(attributes, :message)
- message ||= default_error_message(:blank)
- klass = model_class
-
- attributes.each do |attribute|
- should "require #{attribute} to be set" do
- assert_bad_value(klass, attribute, nil, message)
- end
+ def should_require_attributes(*attributes)
+ message = get_options!(attributes, :message)
+ message ||= default_error_message(:blank)
+ klass = model_class
+
+ attributes.each do |attribute|
+ should "require #{attribute} to be set" do
+ assert_bad_value(klass, attribute, nil, message)
end
end
+ end
- # Ensures that the model cannot be saved if one of the attributes listed is not unique.
- # Requires an existing record
- #
- # Options:
- # * <tt>:message</tt> - value the test expects to find in <tt>errors.on(:attribute)</tt>.
- # Regexp or string. Default = <tt>I18n.translate('activerecord.errors.messages.taken')</tt>
- # * <tt>:scoped_to</tt> - field(s) to scope the uniqueness to.
- #
- # Examples:
- # should_require_unique_attributes :keyword, :username
- # should_require_unique_attributes :name, :message => "O NOES! SOMEONE STOELED YER NAME!"
- # should_require_unique_attributes :email, :scoped_to => :name
- # should_require_unique_attributes :address, :scoped_to => [:first_name, :last_name]
- #
- def should_require_unique_attributes(*attributes)
- message, scope = get_options!(attributes, :message, :scoped_to)
- scope = [*scope].compact
- message ||= default_error_message(:taken)
-
- klass = model_class
- attributes.each do |attribute|
- attribute = attribute.to_sym
- should "require unique value for #{attribute}#{" scoped to #{scope.join(', ')}" unless scope.blank?}" do
- assert existing = klass.find(:first), "Can't find first #{klass}"
- object = klass.new
- existing_value = existing.send(attribute)
-
- if !scope.blank?
- scope.each do |s|
- assert_respond_to object, :"#{s}=", "#{klass.name} doesn't seem to have a #{s} attribute."
- object.send("#{s}=", existing.send(s))
- end
+ # Ensures that the model cannot be saved if one of the attributes listed is not unique.
+ # Requires an existing record
+ #
+ # Options:
+ # * <tt>:message</tt> - value the test expects to find in <tt>errors.on(:attribute)</tt>.
+ # Regexp or string. Default = <tt>I18n.translate('activerecord.errors.messages.taken')</tt>
+ # * <tt>:scoped_to</tt> - field(s) to scope the uniqueness to.
+ #
+ # Examples:
+ # should_require_unique_attributes :keyword, :username
+ # should_require_unique_attributes :name, :message => "O NOES! SOMEONE STOELED YER NAME!"
+ # should_require_unique_attributes :email, :scoped_to => :name
+ # should_require_unique_attributes :address, :scoped_to => [:first_name, :last_name]
+ #
+ def should_require_unique_attributes(*attributes)
+ message, scope = get_options!(attributes, :message, :scoped_to)
+ scope = [*scope].compact
+ message ||= default_error_message(:taken)
+
+ klass = model_class
+ attributes.each do |attribute|
+ attribute = attribute.to_sym
+ should "require unique value for #{attribute}#{" scoped to #{scope.join(', ')}" unless scope.blank?}" do
+ assert existing = klass.find(:first), "Can't find first #{klass}"
+ object = klass.new
+ existing_value = existing.send(attribute)
+
+ if !scope.blank?
+ scope.each do |s|
+ assert_respond_to object, :"#{s}=", "#{klass.name} doesn't seem to have a #{s} attribute."
+ object.send("#{s}=", existing.send(s))
end
- assert_bad_value(object, attribute, existing_value, message)
-
- # Now test that the object is valid when changing the scoped attribute
- # TODO: There is a chance that we could change the scoped field
- # to a value that's already taken. An alternative implementation
- # could actually find all values for scope and create a unique
- # one.
- if !scope.blank?
- scope.each do |s|
- # Assume the scope is a foreign key if the field is nil
- object.send("#{s}=", existing.send(s).nil? ? 1 : existing.send(s).next)
- assert_good_value(object, attribute, existing_value, message)
- end
+ end
+ assert_bad_value(object, attribute, existing_value, message)
+
+ # Now test that the object is valid when changing the scoped attribute
+ # TODO: There is a chance that we could change the scoped field
+ # to a value that's already taken. An alternative implementation
+ # could actually find all values for scope and create a unique
+ # one.
+ if !scope.blank?
+ scope.each do |s|
+ # Assume the scope is a foreign key if the field is nil
+ object.send("#{s}=", existing.send(s).nil? ? 1 : existing.send(s).next)
+ assert_good_value(object, attribute, existing_value, message)
end
end
end
end
+ end
- # Ensures that the attribute cannot be set on mass update.
- #
- # should_protect_attributes :password, :admin_flag
- #
- def should_protect_attributes(*attributes)
- get_options!(attributes)
- klass = model_class
-
- attributes.each do |attribute|
- attribute = attribute.to_sym
- should "protect #{attribute} from mass updates" do
- protected = klass.protected_attributes || []
- accessible = klass.accessible_attributes || []
-
- assert protected.include?(attribute.to_s) ||
- (!accessible.empty? && !accessible.include?(attribute.to_s)),
- (accessible.empty? ?
- "#{klass} is protecting #{protected.to_a.to_sentence}, but not #{attribute}." :
- "#{klass} has made #{attribute} accessible")
- end
+ # Ensures that the attribute cannot be set on mass update.
+ #
+ # should_protect_attributes :password, :admin_flag
+ #
+ def should_protect_attributes(*attributes)
+ get_options!(attributes)
+ klass = model_class
+
+ attributes.each do |attribute|
+ attribute = attribute.to_sym
+ should "protect #{attribute} from mass updates" do
+ protected = klass.protected_attributes || []
+ accessible = klass.accessible_attributes || []
+
+ assert protected.include?(attribute.to_s) ||
+ (!accessible.empty? && !accessible.include?(attribute.to_s)),
+ (accessible.empty? ?
+ "#{klass} is protecting #{protected.to_a.to_sentence}, but not #{attribute}." :
+ "#{klass} has made #{attribute} accessible")
end
end
+ end
- # Ensures that the attribute cannot be changed once the record has been created.
- #
- # should_have_readonly_attributes :password, :admin_flag
- #
- def should_have_readonly_attributes(*attributes)
- get_options!(attributes)
- klass = model_class
+ # Ensures that the attribute cannot be changed once the record has been created.
+ #
+ # should_have_readonly_attributes :password, :admin_flag
+ #
+ def should_have_readonly_attributes(*attributes)
+ get_options!(attributes)
+ klass = model_class
- attributes.each do |attribute|
- attribute = attribute.to_sym
- should "make #{attribute} read-only" do
- readonly = klass.readonly_attributes || []
+ attributes.each do |attribute|
+ attribute = attribute.to_sym
+ should "make #{attribute} read-only" do
+ readonly = klass.readonly_attributes || []
- assert readonly.include?(attribute.to_s),
- (readonly.empty? ?
- "#{klass} attribute #{attribute} is not read-only" :
- "#{klass} is making #{readonly.to_a.to_sentence} read-only, but not #{attribute}.")
- end
+ assert readonly.include?(attribute.to_s),
+ (readonly.empty? ?
+ "#{klass} attribute #{attribute} is not read-only" :
+ "#{klass} is making #{readonly.to_a.to_sentence} read-only, but not #{attribute}.")
end
end
+ end
- # Ensures that the attribute cannot be set to the given values
- #
- # If an instance variable has been created in the setup named after the
- # model being tested, then this method will use that. Otherwise, it will
- # create a new instance to test against.
- #
- # Options:
- # * <tt>:message</tt> - value the test expects to find in <tt>errors.on(:attribute)</tt>.
- # Regexp or string. Default = <tt>I18n.translate('activerecord.errors.messages.invalid')</tt>
- #
- # Example:
- # should_not_allow_values_for :isbn, "bad 1", "bad 2"
- #
- def should_not_allow_values_for(attribute, *bad_values)
- message = get_options!(bad_values, :message)
- message ||= default_error_message(:invalid)
- klass = model_class
- bad_values.each do |v|
- should "not allow #{attribute} to be set to #{v.inspect}" do
- assert_bad_value(klass, attribute, v, message)
- end
+ # Ensures that the attribute cannot be set to the given values
+ #
+ # If an instance variable has been created in the setup named after the
+ # model being tested, then this method will use that. Otherwise, it will
+ # create a new instance to test against.
+ #
+ # Options:
+ # * <tt>:message</tt> - value the test expects to find in <tt>errors.on(:attribute)</tt>.
+ # Regexp or string. Default = <tt>I18n.translate('activerecord.errors.messages.invalid')</tt>
+ #
+ # Example:
+ # should_not_allow_values_for :isbn, "bad 1", "bad 2"
+ #
+ def should_not_allow_values_for(attribute, *bad_values)
+ message = get_options!(bad_values, :message)
+ message ||= default_error_message(:invalid)
+ klass = model_class
+ bad_values.each do |v|
+ should "not allow #{attribute} to be set to #{v.inspect}" do
+ assert_bad_value(klass, attribute, v, message)
end
end
+ end
- # Ensures that the attribute can be set to the given values.
- #
- # If an instance variable has been created in the setup named after the
- # model being tested, then this method will use that. Otherwise, it will
- # create a new instance to test against.
- #
- # Example:
- # should_allow_values_for :isbn, "isbn 1 2345 6789 0", "ISBN 1-2345-6789-0"
- #
- def should_allow_values_for(attribute, *good_values)
- get_options!(good_values)
- klass = model_class
- good_values.each do |v|
- should "allow #{attribute} to be set to #{v.inspect}" do
- assert_good_value(klass, attribute, v)
- end
+ # Ensures that the attribute can be set to the given values.
+ #
+ # If an instance variable has been created in the setup named after the
+ # model being tested, then this method will use that. Otherwise, it will
+ # create a new instance to test against.
+ #
+ # Example:
+ # should_allow_values_for :isbn, "isbn 1 2345 6789 0", "ISBN 1-2345-6789-0"
+ #
+ def should_allow_values_for(attribute, *good_values)
+ get_options!(good_values)
+ klass = model_class
+ good_values.each do |v|
+ should "allow #{attribute} to be set to #{v.inspect}" do
+ assert_good_value(klass, attribute, v)
end
end
+ end
- # Ensures that the length of the attribute is in the given range
- #
- # If an instance variable has been created in the setup named after the
- # model being tested, then this method will use that. Otherwise, it will
- # create a new instance to test against.
- #
- # Options:
- # * <tt>:short_message</tt> - value the test expects to find in <tt>errors.on(:attribute)</tt>.
- # Regexp or string. Default = <tt>I18n.translate('activerecord.errors.messages.too_short') % range.first</tt>
- # * <tt>:long_message</tt> - value the test expects to find in <tt>errors.on(:attribute)</tt>.
- # Regexp or string. Default = <tt>I18n.translate('activerecord.errors.messages.too_long') % range.last</tt>
- #
- # Example:
- # should_ensure_length_in_range :password, (6..20)
- #
- def should_ensure_length_in_range(attribute, range, opts = {})
- short_message, long_message = get_options!([opts], :short_message, :long_message)
- short_message ||= default_error_message(:too_short, :count => range.first)
- long_message ||= default_error_message(:too_long, :count => range.last)
-
- klass = model_class
- min_length = range.first
- max_length = range.last
- same_length = (min_length == max_length)
-
- if min_length > 0
- should "not allow #{attribute} to be less than #{min_length} chars long" do
- min_value = "x" * (min_length - 1)
- assert_bad_value(klass, attribute, min_value, short_message)
- end
- end
-
- if min_length > 0
- should "allow #{attribute} to be exactly #{min_length} chars long" do
- min_value = "x" * min_length
- assert_good_value(klass, attribute, min_value, short_message)
- end
+ # Ensures that the length of the attribute is in the given range
+ #
+ # If an instance variable has been created in the setup named after the
+ # model being tested, then this method will use that. Otherwise, it will
+ # create a new instance to test against.
+ #
+ # Options:
+ # * <tt>:short_message</tt> - value the test expects to find in <tt>errors.on(:attribute)</tt>.
+ # Regexp or string. Default = <tt>I18n.translate('activerecord.errors.messages.too_short') % range.first</tt>
+ # * <tt>:long_message</tt> - value the test expects to find in <tt>errors.on(:attribute)</tt>.
+ # Regexp or string. Default = <tt>I18n.translate('activerecord.errors.messages.too_long') % range.last</tt>
+ #
+ # Example:
+ # should_ensure_length_in_range :password, (6..20)
+ #
+ def should_ensure_length_in_range(attribute, range, opts = {})
+ short_message, long_message = get_options!([opts], :short_message, :long_message)
+ short_message ||= default_error_message(:too_short, :count => range.first)
+ long_message ||= default_error_message(:too_long, :count => range.last)
+
+ klass = model_class
+ min_length = range.first
+ max_length = range.last
+ same_length = (min_length == max_length)
+
+ if min_length > 0
+ should "not allow #{attribute} to be less than #{min_length} chars long" do
+ min_value = "x" * (min_length - 1)
+ assert_bad_value(klass, attribute, min_value, short_message)
end
+ end
- should "not allow #{attribute} to be more than #{max_length} chars long" do
- max_value = "x" * (max_length + 1)
- assert_bad_value(klass, attribute, max_value, long_message)
+ if min_length > 0
+ should "allow #{attribute} to be exactly #{min_length} chars long" do
+ min_value = "x" * min_length
+ assert_good_value(klass, attribute, min_value, short_message)
end
+ end
- unless same_length
- should "allow #{attribute} to be exactly #{max_length} chars long" do
- max_value = "x" * max_length
- assert_good_value(klass, attribute, max_value, long_message)
- end
- end
+ should "not allow #{attribute} to be more than #{max_length} chars long" do
+ max_value = "x" * (max_length + 1)
+ assert_bad_value(klass, attribute, max_value, long_message)
end
- # Ensures that the length of the attribute is at least a certain length
- #
- # If an instance variable has been created in the setup named after the
- # model being tested, then this method will use that. Otherwise, it will
- # create a new instance to test against.
- #
- # Options:
- # * <tt>:short_message</tt> - value the test expects to find in <tt>errors.on(:attribute)</tt>.
- # Regexp or string. Default = <tt>I18n.translate('activerecord.errors.messages.too_short') % min_length</tt>
- #
- # Example:
- # should_ensure_length_at_least :name, 3
- #
- def should_ensure_length_at_least(attribute, min_length, opts = {})
- short_message = get_options!([opts], :short_message)
- short_message ||= default_error_message(:too_short, :count => min_length)
-
- klass = model_class
-
- if min_length > 0
- min_value = "x" * (min_length - 1)
- should "not allow #{attribute} to be less than #{min_length} chars long" do
- assert_bad_value(klass, attribute, min_value, short_message)
- end
- end
- should "allow #{attribute} to be at least #{min_length} chars long" do
- valid_value = "x" * (min_length)
- assert_good_value(klass, attribute, valid_value, short_message)
+ unless same_length
+ should "allow #{attribute} to be exactly #{max_length} chars long" do
+ max_value = "x" * max_length
+ assert_good_value(klass, attribute, max_value, long_message)
end
end
+ end
- # Ensures that the length of the attribute is exactly a certain length
- #
- # If an instance variable has been created in the setup named after the
- # model being tested, then this method will use that. Otherwise, it will
- # create a new instance to test against.
- #
- # Options:
- # * <tt>:message</tt> - value the test expects to find in <tt>errors.on(:attribute)</tt>.
- # Regexp or string. Default = <tt>I18n.translate('activerecord.errors.messages.wrong_length') % length</tt>
- #
- # Example:
- # should_ensure_length_is :ssn, 9
- #
- def should_ensure_length_is(attribute, length, opts = {})
- message = get_options!([opts], :message)
- message ||= default_error_message(:wrong_length, :count => length)
-
- klass = model_class
-
- should "not allow #{attribute} to be less than #{length} chars long" do
- min_value = "x" * (length - 1)
- assert_bad_value(klass, attribute, min_value, message)
- end
+ # Ensures that the length of the attribute is at least a certain length
+ #
+ # If an instance variable has been created in the setup named after the
+ # model being tested, then this method will use that. Otherwise, it will
+ # create a new instance to test against.
+ #
+ # Options:
+ # * <tt>:short_message</tt> - value the test expects to find in <tt>errors.on(:attribute)</tt>.
+ # Regexp or string. Default = <tt>I18n.translate('activerecord.errors.messages.too_short') % min_length</tt>
+ #
+ # Example:
+ # should_ensure_length_at_least :name, 3
+ #
+ def should_ensure_length_at_least(attribute, min_length, opts = {})
+ short_message = get_options!([opts], :short_message)
+ short_message ||= default_error_message(:too_short, :count => min_length)
- should "not allow #{attribute} to be greater than #{length} chars long" do
- max_value = "x" * (length + 1)
- assert_bad_value(klass, attribute, max_value, message)
- end
+ klass = model_class
- should "allow #{attribute} to be #{length} chars long" do
- valid_value = "x" * (length)
- assert_good_value(klass, attribute, valid_value, message)
+ if min_length > 0
+ min_value = "x" * (min_length - 1)
+ should "not allow #{attribute} to be less than #{min_length} chars long" do
+ assert_bad_value(klass, attribute, min_value, short_message)
end
end
+ should "allow #{attribute} to be at least #{min_length} chars long" do
+ valid_value = "x" * (min_length)
+ assert_good_value(klass, attribute, valid_value, short_message)
+ end
+ end
- # Ensure that the attribute is in the range specified
- #
- # If an instance variable has been created in the setup named after the
- # model being tested, then this method will use that. Otherwise, it will
- # create a new instance to test against.
- #
- # Options:
- # * <tt>:low_message</tt> - value the test expects to find in <tt>errors.on(:attribute)</tt>.
- # Regexp or string. Default = <tt>I18n.translate('activerecord.errors.messages.inclusion')</tt>
- # * <tt>:high_message</tt> - value the test expects to find in <tt>errors.on(:attribute)</tt>.
- # Regexp or string. Default = <tt>I18n.translate('activerecord.errors.messages.inclusion')</tt>
- #
- # Example:
- # should_ensure_value_in_range :age, (0..100)
- #
- def should_ensure_value_in_range(attribute, range, opts = {})
- low_message, high_message = get_options!([opts], :low_message, :high_message)
- low_message ||= default_error_message(:inclusion)
- high_message ||= default_error_message(:inclusion)
-
- klass = model_class
- min = range.first
- max = range.last
-
- should "not allow #{attribute} to be less than #{min}" do
- v = min - 1
- assert_bad_value(klass, attribute, v, low_message)
- end
+ # Ensures that the length of the attribute is exactly a certain length
+ #
+ # If an instance variable has been created in the setup named after the
+ # model being tested, then this method will use that. Otherwise, it will
+ # create a new instance to test against.
+ #
+ # Options:
+ # * <tt>:message</tt> - value the test expects to find in <tt>errors.on(:attribute)</tt>.
+ # Regexp or string. Default = <tt>I18n.translate('activerecord.errors.messages.wrong_length') % length</tt>
+ #
+ # Example:
+ # should_ensure_length_is :ssn, 9
+ #
+ def should_ensure_length_is(attribute, length, opts = {})
+ message = get_options!([opts], :message)
+ message ||= default_error_message(:wrong_length, :count => length)
- should "allow #{attribute} to be #{min}" do
- v = min
- assert_good_value(klass, attribute, v, low_message)
- end
+ klass = model_class
- should "not allow #{attribute} to be more than #{max}" do
- v = max + 1
- assert_bad_value(klass, attribute, v, high_message)
- end
+ should "not allow #{attribute} to be less than #{length} chars long" do
+ min_value = "x" * (length - 1)
+ assert_bad_value(klass, attribute, min_value, message)
+ end
- should "allow #{attribute} to be #{max}" do
- v = max
- assert_good_value(klass, attribute, v, high_message)
- end
+ should "not allow #{attribute} to be greater than #{length} chars long" do
+ max_value = "x" * (length + 1)
+ assert_bad_value(klass, attribute, max_value, message)
end
- # Ensure that the attribute is numeric
- #
- # If an instance variable has been created in the setup named after the
- # model being tested, then this method will use that. Otherwise, it will
- # create a new instance to test against.
- #
- # Options:
- # * <tt>:message</tt> - value the test expects to find in <tt>errors.on(:attribute)</tt>.
- # Regexp or string. Default = <tt>I18n.translate('activerecord.errors.messages.not_a_number')</tt>
- #
- # Example:
- # should_only_allow_numeric_values_for :age
- #
- def should_only_allow_numeric_values_for(*attributes)
- message = get_options!(attributes, :message)
- message ||= default_error_message(:not_a_number)
- klass = model_class
- attributes.each do |attribute|
- attribute = attribute.to_sym
- should "only allow numeric values for #{attribute}" do
- assert_bad_value(klass, attribute, "abcd", message)
- end
- end
+ should "allow #{attribute} to be #{length} chars long" do
+ valid_value = "x" * (length)
+ assert_good_value(klass, attribute, valid_value, message)
end
+ end
- # Ensures that the has_many relationship exists. Will also test that the
- # associated table has the required columns. Works with polymorphic
- # associations.
- #
- # Options:
- # * <tt>:through</tt> - association name for <tt>has_many :through</tt>
- # * <tt>:dependent</tt> - tests that the association makes use of the dependent option.
- #
- # Example:
- # should_have_many :friends
- # should_have_many :enemies, :through => :friends
- # should_have_many :enemies, :dependent => :destroy
- #
- def should_have_many(*associations)
- through, dependent = get_options!(associations, :through, :dependent)
- klass = model_class
- associations.each do |association|
- name = "have many #{association}"
- name += " through #{through}" if through
- name += " dependent => #{dependent}" if dependent
- should name do
- reflection = klass.reflect_on_association(association)
- assert reflection, "#{klass.name} does not have any relationship to #{association}"
- assert_equal :has_many, reflection.macro
-
- if through
- through_reflection = klass.reflect_on_association(through)
- assert through_reflection, "#{klass.name} does not have any relationship to #{through}"
- assert_equal(through, reflection.options[:through])
- end
+ # Ensure that the attribute is in the range specified
+ #
+ # If an instance variable has been created in the setup named after the
+ # model being tested, then this method will use that. Otherwise, it will
+ # create a new instance to test against.
+ #
+ # Options:
+ # * <tt>:low_message</tt> - value the test expects to find in <tt>errors.on(:attribute)</tt>.
+ # Regexp or string. Default = <tt>I18n.translate('activerecord.errors.messages.inclusion')</tt>
+ # * <tt>:high_message</tt> - value the test expects to find in <tt>errors.on(:attribute)</tt>.
+ # Regexp or string. Default = <tt>I18n.translate('activerecord.errors.messages.inclusion')</tt>
+ #
+ # Example:
+ # should_ensure_value_in_range :age, (0..100)
+ #
+ def should_ensure_value_in_range(attribute, range, opts = {})
+ low_message, high_message = get_options!([opts], :low_message, :high_message)
+ low_message ||= default_error_message(:inclusion)
+ high_message ||= default_error_message(:inclusion)
+
+ klass = model_class
+ min = range.first
+ max = range.last
+
+ should "not allow #{attribute} to be less than #{min}" do
+ v = min - 1
+ assert_bad_value(klass, attribute, v, low_message)
+ end
- if dependent
- assert_equal dependent.to_s,
- reflection.options[:dependent].to_s,
- "#{association} should have #{dependent} dependency"
- end
+ should "allow #{attribute} to be #{min}" do
+ v = min
+ assert_good_value(klass, attribute, v, low_message)
+ end
- # Check for the existence of the foreign key on the other table
- unless reflection.options[:through]
- if reflection.options[:foreign_key]
- fk = reflection.options[:foreign_key]
- elsif reflection.options[:as]
- fk = reflection.options[:as].to_s.foreign_key
- else
- fk = reflection.primary_key_name
- end
-
- associated_klass_name = (reflection.options[:class_name] || association.to_s.classify)
- associated_klass = associated_klass_name.constantize
-
- assert associated_klass.column_names.include?(fk.to_s),
- "#{associated_klass.name} does not have a #{fk} foreign key."
- end
- end
+ should "not allow #{attribute} to be more than #{max}" do
+ v = max + 1
+ assert_bad_value(klass, attribute, v, high_message)
+ end
+
+ should "allow #{attribute} to be #{max}" do
+ v = max
+ assert_good_value(klass, attribute, v, high_message)
+ end
+ end
+
+ # Ensure that the attribute is numeric
+ #
+ # If an instance variable has been created in the setup named after the
+ # model being tested, then this method will use that. Otherwise, it will
+ # create a new instance to test against.
+ #
+ # Options:
+ # * <tt>:message</tt> - value the test expects to find in <tt>errors.on(:attribute)</tt>.
+ # Regexp or string. Default = <tt>I18n.translate('activerecord.errors.messages.not_a_number')</tt>
+ #
+ # Example:
+ # should_only_allow_numeric_values_for :age
+ #
+ def should_only_allow_numeric_values_for(*attributes)
+ message = get_options!(attributes, :message)
+ message ||= default_error_message(:not_a_number)
+ klass = model_class
+ attributes.each do |attribute|
+ attribute = attribute.to_sym
+ should "only allow numeric values for #{attribute}" do
+ assert_bad_value(klass, attribute, "abcd", message)
end
end
+ end
- # Ensure that the has_one relationship exists. Will also test that the
- # associated table has the required columns. Works with polymorphic
- # associations.
- #
- # Options:
- # * <tt>:dependent</tt> - tests that the association makes use of the dependent option.
- #
- # Example:
- # should_have_one :god # unless hindu
- #
- def should_have_one(*associations)
- dependent = get_options!(associations, :dependent)
- klass = model_class
- associations.each do |association|
- name = "have one #{association}"
- name += " dependent => #{dependent}" if dependent
- should name do
- reflection = klass.reflect_on_association(association)
- assert reflection, "#{klass.name} does not have any relationship to #{association}"
- assert_equal :has_one, reflection.macro
+ # Ensures that the has_many relationship exists. Will also test that the
+ # associated table has the required columns. Works with polymorphic
+ # associations.
+ #
+ # Options:
+ # * <tt>:through</tt> - association name for <tt>has_many :through</tt>
+ # * <tt>:dependent</tt> - tests that the association makes use of the dependent option.
+ #
+ # Example:
+ # should_have_many :friends
+ # should_have_many :enemies, :through => :friends
+ # should_have_many :enemies, :dependent => :destroy
+ #
+ def should_have_many(*associations)
+ through, dependent = get_options!(associations, :through, :dependent)
+ klass = model_class
+ associations.each do |association|
+ name = "have many #{association}"
+ name += " through #{through}" if through
+ name += " dependent => #{dependent}" if dependent
+ should name do
+ reflection = klass.reflect_on_association(association)
+ assert reflection, "#{klass.name} does not have any relationship to #{association}"
+ assert_equal :has_many, reflection.macro
+
+ if through
+ through_reflection = klass.reflect_on_association(through)
+ assert through_reflection, "#{klass.name} does not have any relationship to #{through}"
+ assert_equal(through, reflection.options[:through])
+ end
- associated_klass = (reflection.options[:class_name] || association.to_s.camelize).constantize
+ if dependent
+ assert_equal dependent.to_s,
+ reflection.options[:dependent].to_s,
+ "#{association} should have #{dependent} dependency"
+ end
+ # Check for the existence of the foreign key on the other table
+ unless reflection.options[:through]
if reflection.options[:foreign_key]
fk = reflection.options[:foreign_key]
elsif reflection.options[:as]
fk = reflection.options[:as].to_s.foreign_key
- fk_type = fk.gsub(/_id$/, '_type')
- assert associated_klass.column_names.include?(fk_type),
- "#{associated_klass.name} does not have a #{fk_type} column."
else
- fk = klass.name.foreign_key
+ fk = reflection.primary_key_name
end
+
+ associated_klass_name = (reflection.options[:class_name] || association.to_s.classify)
+ associated_klass = associated_klass_name.constantize
+
assert associated_klass.column_names.include?(fk.to_s),
"#{associated_klass.name} does not have a #{fk} foreign key."
-
- if dependent
- assert_equal dependent.to_s,
- reflection.options[:dependent].to_s,
- "#{association} should have #{dependent} dependency"
- end
end
end
end
+ end
+
+ # Ensure that the has_one relationship exists. Will also test that the
+ # associated table has the required columns. Works with polymorphic
+ # associations.
+ #
+ # Options:
+ # * <tt>:dependent</tt> - tests that the association makes use of the dependent option.
+ #
+ # Example:
+ # should_have_one :god # unless hindu
+ #
+ def should_have_one(*associations)
+ dependent = get_options!(associations, :dependent)
+ klass = model_class
+ associations.each do |association|
+ name = "have one #{association}"
+ name += " dependent => #{dependent}" if dependent
+ should name do
+ reflection = klass.reflect_on_association(association)
+ assert reflection, "#{klass.name} does not have any relationship to #{association}"
+ assert_equal :has_one, reflection.macro
+
+ associated_klass = (reflection.options[:class_name] || association.to_s.camelize).constantize
+
+ if reflection.options[:foreign_key]
+ fk = reflection.options[:foreign_key]
+ elsif reflection.options[:as]
+ fk = reflection.options[:as].to_s.foreign_key
+ fk_type = fk.gsub(/_id$/, '_type')
+ assert associated_klass.column_names.include?(fk_type),
+ "#{associated_klass.name} does not have a #{fk_type} column."
+ else
+ fk = klass.name.foreign_key
+ end
+ assert associated_klass.column_names.include?(fk.to_s),
+ "#{associated_klass.name} does not have a #{fk} foreign key."
- # Ensures that the has_and_belongs_to_many relationship exists, and that the join
- # table is in place.
- #
- # should_have_and_belong_to_many :posts, :cars
- #
- def should_have_and_belong_to_many(*associations)
- get_options!(associations)
- klass = model_class
-
- associations.each do |association|
- should "should have and belong to many #{association}" do
- reflection = klass.reflect_on_association(association)
- assert reflection, "#{klass.name} does not have any relationship to #{association}"
- assert_equal :has_and_belongs_to_many, reflection.macro
- table = reflection.options[:join_table]
- assert ::ActiveRecord::Base.connection.tables.include?(table.to_s), "table #{table} doesn't exist"
+ if dependent
+ assert_equal dependent.to_s,
+ reflection.options[:dependent].to_s,
+ "#{association} should have #{dependent} dependency"
end
end
end
+ end
- # Ensure that the belongs_to relationship exists.
- #
- # should_belong_to :parent
- #
- def should_belong_to(*associations)
- get_options!(associations)
- klass = model_class
- associations.each do |association|
- should "belong_to #{association}" do
- reflection = klass.reflect_on_association(association)
- assert reflection, "#{klass.name} does not have any relationship to #{association}"
- assert_equal :belongs_to, reflection.macro
-
- unless reflection.options[:polymorphic]
- associated_klass = (reflection.options[:class_name] || association.to_s.camelize).constantize
- fk = reflection.options[:foreign_key] || reflection.primary_key_name
- assert klass.column_names.include?(fk.to_s), "#{klass.name} does not have a #{fk} foreign key."
- end
- end
+ # Ensures that the has_and_belongs_to_many relationship exists, and that the join
+ # table is in place.
+ #
+ # should_have_and_belong_to_many :posts, :cars
+ #
+ def should_have_and_belong_to_many(*associations)
+ get_options!(associations)
+ klass = model_class
+
+ associations.each do |association|
+ should "should have and belong to many #{association}" do
+ reflection = klass.reflect_on_association(association)
+ assert reflection, "#{klass.name} does not have any relationship to #{association}"
+ assert_equal :has_and_belongs_to_many, reflection.macro
+ table = reflection.options[:join_table]
+ assert ::ActiveRecord::Base.connection.tables.include?(table.to_s), "table #{table} doesn't exist"
end
end
+ end
- # Ensure that the given class methods are defined on the model.
- #
- # should_have_class_methods :find, :destroy
- #
- def should_have_class_methods(*methods)
- get_options!(methods)
- klass = model_class
- methods.each do |method|
- should "respond to class method ##{method}" do
- assert_respond_to klass, method, "#{klass.name} does not have class method #{method}"
+ # Ensure that the belongs_to relationship exists.
+ #
+ # should_belong_to :parent
+ #
+ def should_belong_to(*associations)
+ get_options!(associations)
+ klass = model_class
+ associations.each do |association|
+ should "belong_to #{association}" do
+ reflection = klass.reflect_on_association(association)
+ assert reflection, "#{klass.name} does not have any relationship to #{association}"
+ assert_equal :belongs_to, reflection.macro
+
+ unless reflection.options[:polymorphic]
+ associated_klass = (reflection.options[:class_name] || association.to_s.camelize).constantize
+ fk = reflection.options[:foreign_key] || reflection.primary_key_name
+ assert klass.column_names.include?(fk.to_s), "#{klass.name} does not have a #{fk} foreign key."
end
end
end
+ end
- # Ensure that the given instance methods are defined on the model.
- #
- # should_have_instance_methods :email, :name, :name=
- #
- def should_have_instance_methods(*methods)
- get_options!(methods)
- klass = model_class
- methods.each do |method|
- should "respond to instance method ##{method}" do
- assert_respond_to klass.new, method, "#{klass.name} does not have instance method #{method}"
- end
+ # Ensure that the given class methods are defined on the model.
+ #
+ # should_have_class_methods :find, :destroy
+ #
+ def should_have_class_methods(*methods)
+ get_options!(methods)
+ klass = model_class
+ methods.each do |method|
+ should "respond to class method ##{method}" do
+ assert_respond_to klass, method, "#{klass.name} does not have class method #{method}"
end
end
+ end
- # Ensure that the given columns are defined on the models backing SQL table.
- #
- # should_have_db_columns :id, :email, :name, :created_at
- #
- def should_have_db_columns(*columns)
- column_type = get_options!(columns, :type)
- klass = model_class
- columns.each do |name|
- test_name = "have column #{name}"
- test_name += " of type #{column_type}" if column_type
- should test_name do
- column = klass.columns.detect {|c| c.name == name.to_s }
- assert column, "#{klass.name} does not have column #{name}"
- end
+ # Ensure that the given instance methods are defined on the model.
+ #
+ # should_have_instance_methods :email, :name, :name=
+ #
+ def should_have_instance_methods(*methods)
+ get_options!(methods)
+ klass = model_class
+ methods.each do |method|
+ should "respond to instance method ##{method}" do
+ assert_respond_to klass.new, method, "#{klass.name} does not have instance method #{method}"
end
end
+ end
- # Ensure that the given column is defined on the models backing SQL table. The options are the same as
- # the instance variables defined on the column definition: :precision, :limit, :default, :null,
- # :primary, :type, :scale, and :sql_type.
- #
- # should_have_db_column :email, :type => "string", :default => nil, :precision => nil, :limit => 255,
- # :null => true, :primary => false, :scale => nil, :sql_type => 'varchar(255)'
- #
- def should_have_db_column(name, opts = {})
- klass = model_class
- test_name = "have column named :#{name}"
- test_name += " with options " + opts.inspect unless opts.empty?
+ # Ensure that the given columns are defined on the models backing SQL table.
+ #
+ # should_have_db_columns :id, :email, :name, :created_at
+ #
+ def should_have_db_columns(*columns)
+ column_type = get_options!(columns, :type)
+ klass = model_class
+ columns.each do |name|
+ test_name = "have column #{name}"
+ test_name += " of type #{column_type}" if column_type
should test_name do
column = klass.columns.detect {|c| c.name == name.to_s }
assert column, "#{klass.name} does not have column #{name}"
- opts.each do |k, v|
- assert_equal column.instance_variable_get("@#{k}").to_s, v.to_s, ":#{name} column on table for #{klass} does not match option :#{k}"
- end
end
end
+ end
- # Ensures that there are DB indices on the given columns or tuples of columns.
- # Also aliased to should_have_index for readability
- #
- # should_have_indices :email, :name, [:commentable_type, :commentable_id]
- # should_have_index :age
- #
- def should_have_indices(*columns)
- table = model_class.table_name
- indices = ::ActiveRecord::Base.connection.indexes(table).map(&:columns)
-
- columns.each do |column|
- should "have index on #{table} for #{column.inspect}" do
- columns = [column].flatten.map(&:to_s)
- assert_contains(indices, columns)
- end
+ # Ensure that the given column is defined on the models backing SQL table. The options are the same as
+ # the instance variables defined on the column definition: :precision, :limit, :default, :null,
+ # :primary, :type, :scale, and :sql_type.
+ #
+ # should_have_db_column :email, :type => "string", :default => nil, :precision => nil, :limit => 255,
+ # :null => true, :primary => false, :scale => nil, :sql_type => 'varchar(255)'
+ #
+ def should_have_db_column(name, opts = {})
+ klass = model_class
+ test_name = "have column named :#{name}"
+ test_name += " with options " + opts.inspect unless opts.empty?
+ should test_name do
+ column = klass.columns.detect {|c| c.name == name.to_s }
+ assert column, "#{klass.name} does not have column #{name}"
+ opts.each do |k, v|
+ assert_equal column.instance_variable_get("@#{k}").to_s, v.to_s, ":#{name} column on table for #{klass} does not match option :#{k}"
end
end
+ end
- alias_method :should_have_index, :should_have_indices
-
- # Ensures that the model cannot be saved if one of the attributes listed is not accepted.
- #
- # If an instance variable has been created in the setup named after the
- # model being tested, then this method will use that. Otherwise, it will
- # create a new instance to test against.
- #
- # Options:
- # * <tt>:message</tt> - value the test expects to find in <tt>errors.on(:attribute)</tt>.
- # Regexp or string. Default = <tt>I18n.translate('activerecord.errors.messages.accepted')</tt>
- #
- # Example:
- # should_require_acceptance_of :eula
- #
- def should_require_acceptance_of(*attributes)
- message = get_options!(attributes, :message)
- message ||= default_error_message(:accepted)
- klass = model_class
-
- attributes.each do |attribute|
- should "require #{attribute} to be accepted" do
- assert_bad_value(klass, attribute, false, message)
- end
+ # Ensures that there are DB indices on the given columns or tuples of columns.
+ # Also aliased to should_have_index for readability
+ #
+ # should_have_indices :email, :name, [:commentable_type, :commentable_id]
+ # should_have_index :age
+ #
+ def should_have_indices(*columns)
+ table = model_class.table_name
+ indices = ::ActiveRecord::Base.connection.indexes(table).map(&:columns)
+
+ columns.each do |column|
+ should "have index on #{table} for #{column.inspect}" do
+ columns = [column].flatten.map(&:to_s)
+ assert_contains(indices, columns)
end
end
+ end
- # Ensures that the model has a method named scope_name that returns a NamedScope object with the
- # proxy options set to the options you supply. scope_name can be either a symbol, or a method
- # call which will be evaled against the model. The eval'd method call has access to all the same
- # instance variables that a should statement would.
- #
- # Options: Any of the options that the named scope would pass on to find.
- #
- # Example:
- #
- # should_have_named_scope :visible, :conditions => {:visible => true}
- #
- # Passes for
- #
- # named_scope :visible, :conditions => {:visible => true}
- #
- # Or for
- #
- # def self.visible
- # scoped(:conditions => {:visible => true})
- # end
- #
- # You can test lambdas or methods that return ActiveRecord#scoped calls:
- #
- # should_have_named_scope 'recent(5)', :limit => 5
- # should_have_named_scope 'recent(1)', :limit => 1
- #
- # Passes for
- # named_scope :recent, lambda {|c| {:limit => c}}
- #
- # Or for
- #
- # def self.recent(c)
- # scoped(:limit => c)
- # end
- #
- def should_have_named_scope(scope_call, *args)
- klass = model_class
- scope_opts = args.extract_options!
- scope_call = scope_call.to_s
-
- context scope_call do
- setup do
- @scope = eval("#{klass}.#{scope_call}")
- end
+ alias_method :should_have_index, :should_have_indices
- should "return a scope object" do
- assert_equal ::ActiveRecord::NamedScope::Scope, @scope.class
- end
+ # Ensures that the model cannot be saved if one of the attributes listed is not accepted.
+ #
+ # If an instance variable has been created in the setup named after the
+ # model being tested, then this method will use that. Otherwise, it will
+ # create a new instance to test against.
+ #
+ # Options:
+ # * <tt>:message</tt> - value the test expects to find in <tt>errors.on(:attribute)</tt>.
+ # Regexp or string. Default = <tt>I18n.translate('activerecord.errors.messages.accepted')</tt>
+ #
+ # Example:
+ # should_require_acceptance_of :eula
+ #
+ def should_require_acceptance_of(*attributes)
+ message = get_options!(attributes, :message)
+ message ||= default_error_message(:accepted)
+ klass = model_class
- unless scope_opts.empty?
- should "scope itself to #{scope_opts.inspect}" do
- assert_equal scope_opts, @scope.proxy_options
- end
+ attributes.each do |attribute|
+ should "require #{attribute} to be accepted" do
+ assert_bad_value(klass, attribute, false, message)
+ end
+ end
+ end
+
+ # Ensures that the model has a method named scope_name that returns a NamedScope object with the
+ # proxy options set to the options you supply. scope_name can be either a symbol, or a method
+ # call which will be evaled against the model. The eval'd method call has access to all the same
+ # instance variables that a should statement would.
+ #
+ # Options: Any of the options that the named scope would pass on to find.
+ #
+ # Example:
+ #
+ # should_have_named_scope :visible, :conditions => {:visible => true}
+ #
+ # Passes for
+ #
+ # named_scope :visible, :conditions => {:visible => true}
+ #
+ # Or for
+ #
+ # def self.visible
+ # scoped(:conditions => {:visible => true})
+ # end
+ #
+ # You can test lambdas or methods that return ActiveRecord#scoped calls:
+ #
+ # should_have_named_scope 'recent(5)', :limit => 5
+ # should_have_named_scope 'recent(1)', :limit => 1
+ #
+ # Passes for
+ # named_scope :recent, lambda {|c| {:limit => c}}
+ #
+ # Or for
+ #
+ # def self.recent(c)
+ # scoped(:limit => c)
+ # end
+ #
+ def should_have_named_scope(scope_call, *args)
+ klass = model_class
+ scope_opts = args.extract_options!
+ scope_call = scope_call.to_s
+
+ context scope_call do
+ setup do
+ @scope = eval("#{klass}.#{scope_call}")
+ end
+
+ should "return a scope object" do
+ assert_equal ::ActiveRecord::NamedScope::Scope, @scope.class
+ end
+
+ unless scope_opts.empty?
+ should "scope itself to #{scope_opts.inspect}" do
+ assert_equal scope_opts, @scope.proxy_options
end
end
end
View
78 lib/shoulda/assertions.rb
@@ -1,48 +1,46 @@
-module ThoughtBot # :nodoc:
- 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
+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 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
+ 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
+ # 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
+ # 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
end
View
520 lib/shoulda/context.rb
@@ -1,306 +1,304 @@
-module Thoughtbot # :nodoc:
- module Shoulda
- VERSION = '2.0.6'
-
- 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
+module Shoulda
+ VERSION = '2.0.6'
- def remove_context # :nodoc:
- self.contexts.pop
- end
+ class << self
+ attr_accessor :contexts
+ def contexts # :nodoc:
+ @contexts ||= []
end
- # == 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
+ def current_context # :nodoc:
+ self.contexts.last
+ end
- def should(name, options = {}, &blk)
- if Shoulda.current_context
- block_given? ? Shoulda.current_context.should(name, options, &blk) : Should.current_context.should_eventually(name)
- else
- context_name = self.name.gsub(/Test/, "")
- context = Thoughtbot::Shoulda::Context.new(context_name, self) do
- block_given? ? should(name, options, &blk) : should_eventually(name)
- end
- context.build
- end
+ def add_context(context) # :nodoc:
+ self.contexts.push(context)
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 }
+ def remove_context # :nodoc:
+ self.contexts.pop
end
+ end
- # Just like should, but never runs, and instead prints an 'X' in the Test::Unit output.
- def should_eventually(name, options = {}, &blk)
+ # == 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
+
+ def should(name, options = {}, &blk)
+ if Shoulda.current_context
+ block_given? ? Shoulda.current_context.should(name, options, &blk) : Should.current_context.should_eventually(name)
+ else
context_name = self.name.gsub(/Test/, "")
- context = Thoughtbot::Shoulda::Context.new(context_name, self) do
- should_eventually(name, &blk)
+ context = Shoulda::Context.new(context_name, self) do
+ block_given? ? should(name, options, &blk) : should_eventually(name)
end
context.build
end
+ 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.
+ # == 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
- def context(name, &blk)
- if Shoulda.current_context
- Shoulda.current_context.context(name, &blk)
- else
- context = Thoughtbot::Shoulda::Context.new(name, self, &blk)
- context.build
- 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
- 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
-
- 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
+ # == 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
- def merge_block(&blk)
- blk.bind(self).call
- 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
+
+ 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 context(name, &blk)
- self.subcontexts << Context.new(name, self, &blk)
- end
+ def merge_block(&blk)
+ blk.bind(self).call
+ end
- def setup(&blk)
- self.setup_blocks << blk
- end
+ def context(name, &blk)
+ self.subcontexts << Context.new(name, self, &blk)
+ end
- def teardown(&blk)
- self.teardown_blocks << blk
- end
+ def setup(&blk)
+ self.setup_blocks << blk
+ end
- def should(name, options = {}, &blk)
- if block_given?
- self.shoulds << { :name => name, :before => options[:before], :block => blk }
- else
- self.should_eventuallys << { :name => name }
- end
- end
+ def teardown(&blk)
+ self.teardown_blocks << blk
+ end
- def should_eventually(name, &blk)
- self.should_eventuallys << { :name => name, :block => blk }
- end
+ def should(name, options = {}, &blk)
+ if block_given?
+ self.shoulds << { :name => name, :before => options[:before], :block => blk }
+ else
+ self.should_eventuallys << { :name => name }
+ end
+ end
- def full_name
- parent_name = parent.full_name if am_subcontext?
- return [parent_name, name].join(" ").strip
- end
+ def should_eventually(name, &blk)
+ self.should_eventuallys << { :name => name, :block => blk }
+ end
- def am_subcontext?
- parent.is_a?(self.class) # my parent is the same class as myself.
- end
+ def full_name
+ parent_name = parent.full_name if am_subcontext?
+ return [parent_name, name].join(" ").strip
+ end
- def test_unit_class
- am_subcontext? ? parent.test_unit_class : parent
- end
+ def am_subcontext?
+ parent.is_a?(self.class) # my parent is the same class as myself.
+ end
- def create_test_from_should_hash(should)
- test_name = ["test:", full_name, "should", "#{should[:name]}. "].flatten.join(' ').to_sym
+ def test_unit_class
+ am_subcontext? ? parent.test_unit_class : parent
+ end
- if test_unit_class.instance_methods.include?(test_name.to_s)
- warn " * WARNING: '#{test_name}' is already defined"
- end
+ def create_test_from_should_hash(should)
+ test_name = ["test:", full_name, "should", "#{should[:name]}. "].flatten.join(' ').to_sym
- context = self
- test_unit_class.send(:define_method, test_name) do
- 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
+ if test_unit_class.instance_methods.include?(test_name.to_s)
+ warn " * WARNING: '#{test_name}' is already defined"
end
- def run_all_setup_blocks(binding)
- run_parent_setup_blocks(binding)
- run_current_setup_blocks(binding)
+ context = self
+ test_unit_class.send(:define_method, test_name) do
+ 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_parent_setup_blocks(binding)
- self.parent.run_all_setup_blocks(binding) if am_subcontext?
- end
+ def run_all_setup_blocks(binding)
+ run_parent_setup_blocks(binding)
+ run_current_setup_blocks(binding)
+ end
- def run_current_setup_blocks(binding)
- setup_blocks.each do |setup_block|
- setup_block.bind(binding).call
- end
- end
+ def run_parent_setup_blocks(binding)
+ self.parent.run_all_setup_blocks(binding) if am_subcontext?
+ 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?
+ def run_current_setup_blocks(binding)
+ setup_blocks.each do |setup_block|
+ setup_block.bind(binding).call
end
+ end
- def print_should_eventuallys
- should_eventuallys.each do |should|
- test_name = [full_name, "should", "#{should[:name]}. "].flatten.join(' ')
- puts " * DEFERRED: " + test_name
- end
+ def run_all_teardown_blocks(binding)
+ teardown_blocks.reverse.each do |teardown_block|
+ teardown_block.bind(binding).call
end