DynamicTeardown

I ran into a situation while working on DeepTest recently where I wanted an object to start a temporary drb server in the middle of the test and have it be stopped automatically at the end of the test. Ideally, I wanted to encapsulate inside the class itself, which is a fake used for testing and so can be aware of the test framework. Here’s the snippet I ended up with:

module DynamicTeardown
  class <<self
    def dynamic_teardowns
      @dynamic_teardowns ||= []
    end

    def on_teardown(&block)
      dynamic_teardowns << block
    end

    def run_dynamic_teardowns
      while td = dynamic_teardowns.shift
        td.call rescue nil
      end
    end
  end
end

module DRbTestHelp
  def drb_server_for(server)
    drb_server = DRb::DRbServer.new "druby://localhost:0", server
    DynamicTeardown.on_teardown { drb_server.stop_service }
    return DRbObject.new_with_uri(drb_server.uri)
  end
end

class Test::Unit::TestCase
  def teardown
    DynamicTeardown.run_dynamic_teardowns
  end
end

This nice little implementation allows the class to know that it needs to get some teardown done while allowing the test framework to determine when the teardowns are called. So far it’s working great for me.