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?
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.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With