How to use Dir.mktmpdir with a block in a hook with rspec?
I want to create a tmpdir in a before
-each hook and use its path in an rspec example. I want to use the block form of Dir.mktmpdir
so the dir is removed at the end of the example.
Problems:
- I can't let the block exit in the
before
hook, or the dir is removed before my example can run. - I can't wrap a block around my example. I tried using an
around
hook, but that doesn't share instance variables with examples (the doc confirms this behavior).
Currently I'm using continuations (Fibers would be better if I were on 1.9) to jump out of the block, then jump back in so mktmpdir
can clean up.
Is there an easier way to accomplish this, without moving mktmpdir
inside each example? It's true that I can remove the dir in the after
-hook, but I'm also looking for a general solution to this type of problem - I don't always know what cleanup code is supposed to run when the block exits.
FYI, my continuation code, encapsulated into a class:
class SuspendableBlock
def initialize
end
def run(&block)
raise LocalJumpError unless block_given?
callcc {|@run_cc|
yield
@resume_cc开发者_高级运维.call if @resume_cc
}
nil
end
# saves the suspend point & causes run to return immediately
def suspend
raise "run must be called first" unless @run_cc
callcc {|@suspend_cc|
@run_cc.call(@suspend_cc)
}
nil
end
# jumps back to after the suspend point to finish the block.
# after the block exits, return immediately from resume.
def resume
raise "suspend must be called first" unless @suspend_cc
callcc {|@resume_cc|
@suspend_cc.call(@resume_cc)
}
nil
end
end
Usage:
before :each do
@sb = SuspendableBlock.new
@sb.run do
Dir.mktmpdir do |dir|
@tmpdir_path = Pathname.new(dir)
@sb.suspend
end
end
end
after :each do
@sb.resume
end
it "should use a tmp dir" do
p @tmpdir_path
end
From what I read (never tested it) continuations are really inefficient.
While I cannot help you on continuations you could use Thread to mimic Fibers: https://github.com/tmm1/fiber18.
One library which already does that is em-spec (https://github.com/tmm1/em-spec), with it each test is ran in a fiber you may be able to modify it to match your needs.
精彩评论