测试时间关键代码

时间:2009-11-17 13:06:56

标签: ruby unit-testing time

我为我的库Rubikon编写了一个功能,只要其他一些代码正在运行,它就会显示一个悸动者(正如您在其他控制台应用中看到的那样)。

要测试此功能,我会在StringIO中捕获throbber的输出,并将其与预期值进行比较。由于仅在其他代码运行时才显示throbber,因此当代码运行更长时,IO的内容会变长。在我的测试中,我做了一个简单的sleep 1,并且应该有一个恒定的1秒延迟。这大部分时间都可以工作,但有时候(显然是由于外部因素,如CPU上的负载很大),它会失败,因为代码不会运行1秒钟,但会更多一些,因此throbber会打印一些额外的字符。

我的问题是:是否有可能在Ruby中测试这些时间关键功能?

2 个答案:

答案 0 :(得分:2)

从你的github存储库中,我发现了Throbber类的测试:

should 'work correctly' do
  ostream = StringIO.new
  thread = Thread.new { sleep 1 }
  throbber = Throbber.new(ostream, thread)
  thread.join
  throbber.join
  assert_equal " \b-\b\\\b|\b/\b", ostream.string
end

我会假设一个throbber迭代['-', '\', '|', '/'],每次写入前退一步,每秒一次。考虑以下测试:

should 'work correctly' do
  ostream = StringIO.new
  started_at = Time.now
  ended_at = nil
  thread = Thread.new { sleep 1; ended_at = Time.now }
  throbber = Throbber.new(ostream, thread)
  thread.join
  throbber.join
  duration = ended_at - started_at
  iterated_chars = " -\\|/"
  expected = ""
  if duration >= 1
    # After n seconds we should have n copies of " -\\|/", excluding \b for now
    expected << iterated_chars * duration.to_i
  end
  # Next append the characters we'd get from working for fractions of a second:
  remainder = duration - duration.to_i
  expected << iterated_chars[0..((iterated_chars.length*remainder).to_i)] if remainder > 0.0
  expected = expected.split('').join("\b") + "\b"
  assert_equal expected, ostream.string
end

expected的最后一个分配有点不愉快,但我假设throbber会原子地写字符/退格对。如果不是这样,您应该能够将\ b转义序列插入到iterated_chars字符串中并完全删除最后一个赋值。

答案 1 :(得分:1)

这个问题与this one类似(我认为,尽管我不完全确定):

  

只有实时操作系统才能   给你这么精准。您可以   假设Thread.Sleep的精度为   大约20毫秒所以你理论上可以   睡到所需的时间 -   实际时间约为20毫秒   旋转20毫秒,但你必须   浪费那20毫秒。甚至那个   并不保证你会变得真实   时间结果,调度程序可能只是   当它出现时,把你的线程拿出来   即将执行RELEVANT部分   (刚刚旋转后)

问题不是rubby(可能,我不是ruby的专家),问题是你的操作系统的实时功能。