Created
February 22, 2010 00:11
-
-
Save xaviershay/310639 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# In Rspec, gives you: | |
# before(:all_transactional) {} | |
# | |
# Uses nested transactions to correctly rollback :all before blocks | |
# You *may* need to reload some instance variables in a separate before(:each) block | |
# All a bit of a hack, but really handy | |
module RspecRailsTransactions | |
def before_all_transactional_parts # :nodoc: | |
@before_all_transactional_parts ||= [] | |
end | |
# Overridden from rspec implementation to add :all_transactional | |
def before_parts(scope) | |
case scope | |
when :each; before_each_parts | |
when :all; before_all_parts | |
when :suite; before_suite_parts | |
when :all_transactional; before_all_transactional_parts | |
end | |
end | |
# Based on a combination of run_before_all and run_after_all methods from rspec | |
def run_before_all_transactional_parts(success, run_options, instance_variables) | |
return [success, instance_variables] if example_group_hierarchy.before_all_transactional_parts.empty? | |
example_proxy = ::Spec::Example::ExampleProxy.new("before(:all_transactional)") | |
before_all = new(example_proxy) | |
before_all.set_instance_variables_from_hash(instance_variables) | |
example_group_hierarchy.run_before_all_transactional(before_all) | |
[success, before_all.instance_variable_hash] | |
rescue Exception => e | |
run_options.reporter.example_failed(example_proxy, e) | |
[false, before_all.instance_variable_hash] | |
end | |
# Overridden from the rspec implementation, as it doesn't provide us with necessary hooks | |
def run_examples(success, instance_variables, examples, run_options) | |
return [success, instance_variables] unless success | |
after_all_instance_variables = instance_variables | |
ActiveSupport::TestCase.use_transactional_fixtures = false | |
ActiveRecord::Base.transaction(:joinable => false) do | |
success, instance_variables = run_before_all_transactional_parts(success, run_options, instance_variables) | |
if success | |
examples.each do |example| | |
example_group_instance = new(example, &example_implementations[example]) | |
# .transaction doesn't work here | |
ActiveRecord::Base.connection.create_savepoint | |
ActiveRecord::Base.connection.increment_open_transactions | |
success &= example_group_instance.execute(run_options, instance_variables) | |
ActiveRecord::Base.connection.decrement_open_transactions | |
ActiveRecord::Base.connection.rollback_to_savepoint | |
after_all_instance_variables = example_group_instance.instance_variable_hash | |
end | |
end | |
raise ActiveRecord::Rollback | |
end | |
return [success, after_all_instance_variables] | |
end | |
end | |
module Spec | |
module Example | |
class ExampleGroupHierarchy < Array | |
# Fail fast call was cargo-culted, I need to investigate further | |
def run_before_all_transactional(example) | |
example.eval_each_fail_fast(before_all_transactional_parts) | |
end | |
# Not all of the hierachy has necessary been extended with transactional | |
# support, so check that each klass responds to the method first | |
def before_all_transactional_parts | |
@before_all_transactional_parts ||= collect {|klass| klass.before_all_transactional_parts if klass.respond_to?(:before_all_transactional_parts) }.compact.flatten | |
end | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment