public

  • Download Gist
rspec_rails_transactional.rb
Ruby
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
# 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

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.