views:

76

answers:

2
+2  A: 

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.

Ian
Sounds good, I'll check this one.
Koraktor
+1  A: 

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.

Jorge Córdoba
I know that I can't expect real time behaviour from a non-realtime OS and especially from a script language like Ruby. My question is not about eliminating delays to get real time behaviour, I just want to eliminate side effects in unit tests.
Koraktor