3

这是我遇到的情况的一个最小的通用示例:

测试/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_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

TestUtils模块包含在每个测试文件中,因此始终执行公共beforeend任务,但在这种情况下,我还需要将该方法temporary_change_value用作该文件中所有测试的前块。这不起作用,似乎只有一个before/end块被执行(特别是设置的那个MyMainClass.interface

我尝试过的事情

我试图改变before/end块的顺序,就像这样。

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

还是行不通。现在settings值没有改变,所以它似乎是第二个before/end块,包括唯一一个被执行的。

问题:我怎样才能做到这一点并且仍然保持干燥?

4

2 回答 2

2

从 MiniTest 3.3 开始,before/end 只是方法,而不是钩子,所以当您调用 before do ... end 时,您将覆盖以前的 before 方法。您可以使用的是MiniTest::TestCase.add_setup_hookhttp://bfts.rubyforge.org/minitest/MiniTest/Unit/TestCase.html#method-c-add_setup_hook)。您应该能够将代码放在该特定测试用例中temporary_change_value()的块内,以实现您正在寻找的内容。add_setup_hook

于 2013-04-10T19:15:15.763 回答
1

感谢 Minitest gem @zenspider 的维护者,我终于设法解决了这个问题。

测试/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_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
于 2013-05-16T15:34:21.087 回答