Reputation: 5268
This a minimal generic example of the situation I have:
test/mytest.rb
describe "What I want to test" do
include TestUtils
temporary_change_value(settings, :tmp_setting, value)
describe "test1 blablabla" do
# ...
end
describe "test2 blablabla" do
# ...
end
end
test/support/test_utils.rb
module TestUtils
def self.included(base)
base.class_eval do
extend ClassMethods
before do
MyMainClass.interface = TestInterface.new
MyMainClass.handler.display.clear
end
after do
MyMainClass.handler.display.clear
end
end
end
module ClassMethods
def temporary_change_value(item, key, value)
old_value = nil
before do
old_value = item[key]
item[key] = value
end
after do
item[key] = old_value
end
end
end
end
The TestUtils
module is included in evey test file so the common before
and end
tasks are always executed, but in this case I also need to use the method temporary_change_value
as a before block for all the tests in this file. This is not working, it seems that only one of the before
/end
blocks gets executed (specifically the one that sets MyMainClass.interface
)
Things I've tried
I've tried to change the order of the before
/end
blocks, like this.
describe "What I want to test" do
extend TestUtils::ClassMethods
temporary_change_value(settings, :tmp_setting, value)
include TestUtils
describe "test1 blablabla" do
# ...
end
describe "test2 blablabla" do
# ...
end
end
Still not working. Now the settings
value doesn't get changed, so it seems that it is the second before
/end
block included the only one that gets executed.
The question: How can I achieve this and still keep it DRY?
Upvotes: 3
Views: 1299
Reputation: 5268
I finally managed to solve this thanks to the mantainer of the Minitest gem @zenspider.
test/my_test.rb
class TestWhatIWant < TestUtils::TestCase
temporary_change_value settings, :tmp_setting, value
describe "test1 blablabla" do
# ...
end
describe "test2 blablabla" do
# ...
end
end
test/support/test_utils.rb
module TestUtils
module ClassUtils
def temporary_change_value item, key, value
mod = Module.new do
extend Minitest::Spec::DSL
before do
@old_value = item[key]
item[key] = value
end
after do
item[key] = @old_value
end
end
include mod
end
class TestCase < Minitest::Spec
extend TestUtils::ClassUtils
include TestUtils
def setup
Byebug.interface = TestInterface.new
Byebug.handler.display.clear
end
end
end
end
Upvotes: 1
Reputation: 21
Since MiniTest 3.3, before/end are just methods, not hooks, so when you call before do ... end, you are overwriting what used to be your before method. What you can use instead is MiniTest::TestCase.add_setup_hook
(http://bfts.rubyforge.org/minitest/MiniTest/Unit/TestCase.html#method-c-add_setup_hook). You should be able to put the code from temporary_change_value()
inside an add_setup_hook
block in that particular test case to achieve what you're looking for.
Upvotes: 2