【问题标题】:Speed up "sleep" in Ruby加速 Ruby 中的“睡眠”
【发布时间】:2014-09-12 08:01:25
【问题描述】:

在我的代码中,有很多地方我特意设置了“睡眠”,只是因为功能需要如此。但是,当我使用 RSpec 或 Cucumber 进行测试时,它会变得很麻烦,因为完成测试需要很长时间。

更新:感谢您的一些建议。但是,存根或手动重新定义可能很麻烦。我想象的只是一个调整调用,以加快“睡眠”的规模。

有这个宝石时间轴。它可以按比例加速 Time.now。如果这样的想法可以应用到睡眠中,那就太好了!

参考: https://github.com/travisjeffery/timecop


更新:抱歉回复晚了,下面可以说明我的情况:

class SomeClass
    def some_method
        sleep 15
        make_api_call_A
        sleep 45
        make_api_call_B
    end
end

describe SomeClass do
    before do
        Acceleration.speed_up(10) # speed time up to 10x
    end

    after do
        Acceleration.reset
    end

    if "should make two API calls" do
        subject.some_method
    end
end

如您所见,在 some_method 中有两个不同持续时间的睡眠。我更喜欢的是,如果我可以将睡眠时间加快到 10 倍,而不是等待 60s,我只需要等待 6s。这大大加快了测试过程。

【问题讨论】:

  • 只需将硬编码的sleep 值替换为变量/配置即可。
  • 我不确定我是否理解您的问题。你能添加一个你的功能需要sleep的例子吗?
  • 存根“麻烦”如何?存根就是为此而发明的。
  • 你为什么要使用睡眠?请改用轮询。
  • 你好,我更新了我的问题,如果你还有兴趣请看一下。

标签: ruby testing rspec cucumber sleep


【解决方案1】:

您的规范中需要存根 sleep 调用。

class SomeClass
  def some_method
    sleep 10
  end
end

describe SomeClass do
  before do
    subject.stub!(:sleep)
  end

  it "should call sleep" do
    subject.should_receive(:sleep).with(10)
    subject.some_method
  end
end

【讨论】:

  • 您好,我更新了我的问题,如果您仍有兴趣,请查看。
【解决方案2】:

如果你想扩展睡眠,你可以这样覆盖Kernel.sleep方法:

module Acceleration
  mattr_accessor :sleep_scale

  def self.speed_up(scale)
    self.sleep_scale = scale
  end

  def self.reset
    self.sleep_scale = 1
  end

  reset
end

module Kernel
  alias :original_sleep :sleep

  def sleep(time)
    original_sleep(time / Acceleration.sleep_scale.to_f)
  end
end

class SomeClass
  def some_method
      sleep 15
      make_api_call_A
      sleep 45
      make_api_call_B
  end
end

describe SomeClass do
  before do
    Acceleration.speed_up(10) # speed time up to 10x
  end

  after do
    Acceleration.reset
  end

  it "should make two API calls" do
    subject.some_method
  end
end

【讨论】:

  • 嗨,德米特里,非常感谢。有用。此外,我会合并更多功能以使其成为宝石。你想在它出版时得到认可吗? :)
【解决方案3】:

仅在测试时临时添加以下内容。

def sleep *; end

【讨论】:

    【解决方案4】:

    猴子补丁内核#sleep

    假设您在这里确实有一个有效的用例,并且您不想重构代码以避免硬编码睡眠值或完全禁用睡眠,您可以简单地在您的规范中使用猴子补丁 Kernel#sleep一个比例因子。例如,要让 sleep 运行速度快十倍(例如指定时间的 1/10):

    module Kernel
      alias_method :old_sleep, :sleep
      def sleep seconds
        old_sleep(seconds * 0.1)
      end  
    end
    

    对您的扩展进行基准测试

    猴子修补睡眠后,您可以测试您的缩放是否适用于Benchmark#realtime

    require 'benchmark'
    
    Benchmark.realtime { sleep 10 }.round 2
    #=> 1.0
    
    Benchmark.realtime { sleep 0.1 }.round 2
    #=> 0.01
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-04-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-08-22
      • 1970-01-01
      • 2013-04-22
      • 1970-01-01
      相关资源
      最近更新 更多