2009-11-17 46 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