如何使用 Dir.mktmpdir 与带有 rspec 的钩子中的块?

发布于 2024-11-27 13:30:27 字数 1632 浏览 0 评论 0原文

我想在 before-each 挂钩中创建一个 tmpdir 并在 rspec 示例中使用其路径。我想使用 Dir.mktmpdir 的块形式,以便在示例末尾删除该目录。

问题:

  • 我无法让块在 before 挂钩中退出,或者在我的示例运行之前删除目录。
  • 我无法将我的示例包裹起来。我尝试使用 around 钩子,但它不与示例共享实例变量( doc 确认了此行为)。

目前,我正在使用延续(如果我在 1.9 上,纤维会更好)跳出块,然后跳回,以便 mktmpdir 可以清理。

有没有更简单的方法来完成此任务,而无需在每个示例中移动 mktmpdir ?确实,我可以删除 after-hook 中的目录,但我也在寻找此类问题的通用解决方案 - 我并不总是知道应该运行什么清理代码当块退出时。

仅供参考,我的延续代码,封装到一个类中:

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

用法:

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

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

極樂鬼 2024-12-04 13:30:27

从我读到的(从未测试过)来看,延续的效率确实很低。

虽然我无法帮助您继续,但您可以使用 Thread 来模仿 Fiber: https://github.com/tmm1/ Fiber18< /a>.

em-spec (https://github.com/tmm1/em-spec) 已经做到了这一点,它的每个测试都在光纤中运行,您可以对其进行修改以满足您的需求。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文