我为我的库Rubikon编写了一个功能,只要其他一些代码正在运行,它就会显示一个悸动者(正如您在其他控制台应用中看到的那样)。
要测试此功能,我会在StringIO
中捕获throbber的输出,并将其与预期值进行比较。由于仅在其他代码运行时才显示throbber,因此当代码运行更长时,IO
的内容会变长。在我的测试中,我做了一个简单的sleep 1
,并且应该有一个恒定的1秒延迟。这大部分时间都可以工作,但有时候(显然是由于外部因素,如CPU上的负载很大),它会失败,因为代码不会运行1秒钟,但会更多一些,因此throbber会打印一些额外的字符。
我的问题是:是否有可能在Ruby中测试这些时间关键功能?
答案 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的专家),问题是你的操作系统的实时功能。