2014-01-25 32 views
1

我想要習慣用簡單的驅動程序片段來測試我的代碼,並且想要測試一個參數錯誤是否在不脫離程序的情況下拋出。這裏是我使用的代碼有沒有辦法從一個方法內測試參數錯誤來返回true或false?

class Die 
    def initialize(sides) 
    @sides=sides 
    unless @sides>0 
     raise ArgumentError.new("Your number sucks, yo") 
    end 
    end 

    #returns the number of sides of a die 
    def sides 
    @sides 
    end 

    #generates a random die roll based on the number of sides 
    def roll 
    rand(@sides)+1 
    end 
end 

這裏是我正試圖調用來獲得測試。

p bad=Die.new(0)=="Your number sucks, yo" 

我希望它返回的是「true」。它在終端返回的是:

w3p1_refact.rb:33:in `initialize': Your number sucks, yo (ArgumentError) 
    from w3p1_refact.rb:69:in `new' 
    from w3p1_refact.rb:69:in `<main>' 

我可以重寫這個以返回我在找什麼嗎?

回答

4

Exception

當一個異常被提出,但尚未處理的文檔(rescueensureat_exitEND塊)全局變量$!將包含當前異常,並且$ @包含當前異常的回溯。

所以一旦我剛纔提出的$!全局變量例外,我可以用Exception#message方法,它返回異常的消息或名稱。

您使用Kernel#raise

不帶任何參數,引發異常的$!或者如果$!引發RuntimeError是零。 使用單個String參數引發RuntimeError,並將該字符串作爲消息。否則,第一個參數應該是Exception類的名稱(或發送異常消息時返回Exception對象的對象)。可選的第二個參數設置與異常關聯的消息,第三個參數是一個回調信息數組。 異常由begin ... end塊的救援條款捕獲。

我會做如下:

class Die 
    def initialize(sides) 
    @sides=sides 
    unless @sides>0 
     raise ArgumentError.new("Your number sucks, yo") 
     # As per the doc you could write the above line as below also 
     # raise ArgumentError, "Your number sucks, yo" 
    end 
    end 

    #returns the number of sides of a die 
    def sides 
    @sides 
    end 

    #generates a random die roll based on the number of sides 
    def roll 
    rand(@sides)+1 
    end 
end 

Die.new(0) rescue $!.message == "Your number sucks, yo" 
# => true 

以上內嵌救援代碼可以寫成也:

begin 
    Die.new(0) 
rescue ArgumentError => e 
    bad = e.message 
end 
bad == "Your number sucks, yo" # => true 
+1

我認爲這將有助於拼出用'開始...救援ArgumentError => e ... end'塊來拯救,這樣它就完全清楚你在做什麼,並且還要注意你在這裏的縮短形式不太明顯。 – jeremycole

+1

@jeremycole我認爲它會工作,根據代碼。因爲該消息將被設置,只有當異常來自該部分。否則,它總會是'假'。 –

+2

是的,我知道它的工作原理,但我認爲它作爲解釋的幫助很少。很明顯,提問者不知道「救援」是否正確,如果你要提供一個答案和例子,它應該是一個有用的答案。我的意見當然。 – jeremycole

相關問題