aboutsummaryrefslogtreecommitdiffstats
path: root/activesupport/lib/active_support/testing/setup_and_teardown.rb
diff options
context:
space:
mode:
Diffstat (limited to 'activesupport/lib/active_support/testing/setup_and_teardown.rb')
-rw-r--r--activesupport/lib/active_support/testing/setup_and_teardown.rb127
1 files changed, 127 insertions, 0 deletions
diff --git a/activesupport/lib/active_support/testing/setup_and_teardown.rb b/activesupport/lib/active_support/testing/setup_and_teardown.rb
new file mode 100644
index 0000000000..1639462fae
--- /dev/null
+++ b/activesupport/lib/active_support/testing/setup_and_teardown.rb
@@ -0,0 +1,127 @@
+module ActiveSupport
+ module Testing
+ module SetupAndTeardown
+ def self.included(base)
+ base.extend ClassMethods
+
+ begin
+ require 'mocha'
+ base.alias_method_chain :run, :callbacks_and_mocha
+ rescue LoadError
+ base.alias_method_chain :run, :callbacks
+ end
+ end
+
+ module ClassMethods
+ def setup(*method_names, &block)
+ method_names << block if block_given?
+ (@setup_callbacks ||= []).concat method_names
+ end
+
+ def teardown(*method_names, &block)
+ method_names << block if block_given?
+ (@teardown_callbacks ||= []).concat method_names
+ end
+
+ def setup_callback_chain
+ @setup_callbacks ||= []
+
+ if superclass.respond_to?(:setup_callback_chain)
+ superclass.setup_callback_chain + @setup_callbacks
+ else
+ @setup_callbacks
+ end
+ end
+
+ def teardown_callback_chain
+ @teardown_callbacks ||= []
+
+ if superclass.respond_to?(:teardown_callback_chain)
+ superclass.teardown_callback_chain + @teardown_callbacks
+ else
+ @teardown_callbacks
+ end
+ end
+ end
+
+ # This redefinition is unfortunate but test/unit shows us no alternative.
+ def run_with_callbacks(result) #:nodoc:
+ return if @method_name.to_s == "default_test"
+
+ yield(Test::Unit::TestCase::STARTED, name)
+ @_result = result
+ begin
+ run_callbacks :setup
+ setup
+ __send__(@method_name)
+ rescue Test::Unit::AssertionFailedError => e
+ add_failure(e.message, e.backtrace)
+ rescue *Test::Unit::TestCase::PASSTHROUGH_EXCEPTIONS
+ raise
+ rescue Exception
+ add_error($!)
+ ensure
+ begin
+ teardown
+ run_callbacks :teardown, :reverse_each
+ rescue Test::Unit::AssertionFailedError => e
+ add_failure(e.message, e.backtrace)
+ rescue *Test::Unit::TestCase::PASSTHROUGH_EXCEPTIONS
+ raise
+ rescue Exception
+ add_error($!)
+ end
+ end
+ result.add_run
+ yield(Test::Unit::TestCase::FINISHED, name)
+ end
+
+ # Doubly unfortunate: mocha does the same so we have to hax their hax.
+ def run_with_callbacks_and_mocha(result)
+ return if @method_name.to_s == "default_test"
+
+ yield(Test::Unit::TestCase::STARTED, name)
+ @_result = result
+ begin
+ mocha_setup
+ begin
+ run_callbacks :setup
+ setup
+ __send__(@method_name)
+ mocha_verify { add_assertion }
+ rescue Mocha::ExpectationError => e
+ add_failure(e.message, e.backtrace)
+ rescue Test::Unit::AssertionFailedError => e
+ add_failure(e.message, e.backtrace)
+ rescue StandardError, ScriptError
+ add_error($!)
+ ensure
+ begin
+ teardown
+ run_callbacks :teardown, :reverse_each
+ rescue Test::Unit::AssertionFailedError => e
+ add_failure(e.message, e.backtrace)
+ rescue StandardError, ScriptError
+ add_error($!)
+ end
+ end
+ ensure
+ mocha_teardown
+ end
+ result.add_run
+ yield(Test::Unit::TestCase::FINISHED, name)
+ end
+
+ protected
+ def run_callbacks(kind, enumerator = :each)
+ self.class.send("#{kind}_callback_chain").send(enumerator) do |callback|
+ case callback
+ when Proc; callback.call(self)
+ when String, Symbol; send!(callback)
+ else raise ArgumentError, "Unrecognized callback #{callback.inspect}"
+ end
+ end
+ end
+ end
+ end
+end