开发者

Testing time critical code

I've written a feature for my library Rubikon that displays a throbber (a spinning — as you may have seen in other console apps) as long as some other code is running.

To test this feature I capture the output of the throbber in a StringIO and compare it with the expected value. As the throbber is only displayed as long as the other code is running the content of the IO ge开发者_如何转开发ts longer when the code runs longer. In my tests I do a simple sleep 1 and should have a constant 1 second delay. This works most of the time, but sometimes (apparently due to external factors like heavy load on the CPU) it fails, because the code doesn't run for 1 second, but for a bit more, so that the throbber prints a few additional characters.

My question is: Is there any possibility to test such time critical features in Ruby?


From your github repository, I found this test for the Throbber class:

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

I'll assume that a throbber iterates over ['-', '\', '|', '/'], backspacing before each write, once per second. Consider the following test:

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

The last assignment of expected is a bit unpleasant, but I made the assumption that the throbber would write character/backspace pairs atomically. If this is not true, you should be able to insert the \b escape sequence into the iterated_chars string and remove the last assignment entirely.


This question is similar (I think, altough I'm not completely sure) to this one:

Only real time operating system can give you such precision. You can assume Thread.Sleep has a precision of about 20 ms so you could, in theory sleep until the desired time - the actual time is about 20 ms and THEN spin for 20 ms but you'll have to waste those 20 ms. And even that doesn't guarantee that you'll get real time results, the scheduler might just take your thread out just when it was about to execute the RELEVANT part (just after spinning)

The problem is not rubby (possibly, I'm no expert in ruby), the problem is the real time capabilities of your operating system.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜