2

単純なドライバー スニペットを使用してコードをテストすることに慣れようとしており、プログラムからエスケープせずに引数エラーがスローされるかどうかをテストしたいと考えています。これが私が使用しているコードです

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"

返してほしいのは「真」です。ターミナルで返されるのは次のとおりです。

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

1 に答える 1

5

例外のドキュメントから

例外が発生したが、まだ処理されていない場合 ( rescueensureat_exitおよびENDブロック内) 、グローバル変数 $! には現在の例外が含まれ、 $@ には現在の例外のバックトレースが含まれます。

したがって、$!グローバル変数で例外を発生させたら、例外のメッセージまたは名前Exception#messageを返すメソッドを使用できます。

あなたが使うKernel#raise

引数なしで、$! で例外を発生させます。$! の場合は RuntimeError を発生させます。はゼロです。String 引数を 1 つ指定すると、その文字列をメッセージとして RuntimeError を発生させます。それ以外の場合、最初のパラメーターは Exception クラス (または例外メッセージが送信されたときに Exception オブジェクトを返すオブジェクト) の名前にする必要があります。オプションの 2 番目のパラメーターは例外に関連付けられたメッセージを設定し、3 番目のパラメーターはコールバック情報の配列です。例外は、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
于 2014-01-25T17:53:15.843 に答える