2009-11-17 53 views
1

我已经为我的图书馆Rubikon编写了一个功能,只要其他代码正在运行,它就会显示一个跳动(在其他控制台应用程序中看到的旋转—)。测试时间关键代码

为了测试此功能,我捕获了StringIO中的跳动输出并将其与期望值进行比较。由于只有在其他代码正在运行时才显示跳动者,所以当代码运行更长时,IO的内容会变得更长。在我的测试中,我做了一个简单的sleep 1,并且应该有一个恒定的1秒延迟。这在大多数情况下都是有效的,但有时(显然是由于外部因素,例如CPU负载过重),它会失败,因为代码不会运行1秒,但会稍微增加一点,这样跳动者就会打印一些额外的内容字符。

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

回答

2

从你的GitHub库,我发现这个测试的活动指示器类:

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 

我假设一个活动指示器迭代['-', '\', '|', '/'],退格每次写之前,每秒一次。请看下面的测试:

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最后的分配是有点不愉快,但我的假设是,活动指示器会写字符/退格对原子。如果不是这样,您应该能够将\ b转义序列插入到iterated_chars字符串中,并完全删除最后一个分配。

+0

听起来不错,我会检查一下。 – Koraktor 2009-11-17 21:44:17

1

这个问题是相似的(我想,altough我不能完全确定),以this one

只有实时操作系统可 给你这样的精确度。您可以 承担了Thread.Sleep有 约20毫秒的精确度,所以你可以在理论上 休眠状态,直到所需的时间 - 实际时间约为20毫秒,然后 自旋为20毫秒,但你必须 浪费那些20毫秒。甚至认为 并不能保证你会得到真正的 时间的结果,调度可能只是 把你的线程出来只是当它是 即将执行的相关部分 (刚纺丝后)

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

+0

我知道我不能期望来自非实时操作系统的实时行为,特别是像Ruby这样的脚本语言。我的问题不是关于消除拖延来获得实时行为,我只是想消除单元测试中的副作用。 – Koraktor 2009-11-17 21:46:34