Skip to content

Instantly share code, notes, and snippets.

@kjlape
Last active October 6, 2020 14:25
Show Gist options
  • Save kjlape/cc0b87056fae83b94ab09c34e2f9bcbc to your computer and use it in GitHub Desktop.
Save kjlape/cc0b87056fae83b94ab09c34e2f9bcbc to your computer and use it in GitHub Desktop.
Experimental Minitest around_each hook

Characteristics

  • Completely wraps the minitest test lifecycle (setup, teardown, and friends…). This may lead to surprising results.
  • Supports multiple calls to around_each. Each subsequent around_each call wraps around the previous one. Is this unintuitive? I don't know. 🤷‍♂️
require "minitest/mock"
class SomeTest < ActionDispatch::IntegrationTest
around_each do |test|
Widget.stub(:relevant_state, "test value", &test)
end
around_each do |test|
DB.with_rollback do
DB.do_a_bunch_of_destructive_stuff
test.call
end
end
def test_widget_in_transaction
assert_equal "test value", Widget.relevant_state
assert DB.destructive_stuff_happened?
end
end
module AroundEachTest
def self.included(m)
m.mattr_accessor :around_block
m.extend(ClassMethods)
end
module ClassMethods
def around_each(&block)
self.around_block = around_block.yield_self { |inner_around_block|
if inner_around_block.nil?
Proc.new do |instance, test_run|
instance.instance_exec(test_run, &block)
end
else
Proc.new do |instance, test_run|
instance.instance_exec(Proc.new { inner_around_block.call(instance, test_run) }, &block)
end
end
}
end
end
end
class ActiveSupport::TestCase
include AroundEachTest
# …
end
Minitest::Test.prepend(
Module.new do
def run(*)
if around_block.present?
[].tap { |results|
around_block.call(self, Proc.new { results << super })
}.first
else
super
end
end
end
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment