assertの基本から

前回の日記と順番は前後してしまったが、今まで適当に使っていたassertについても見直してみた。

基本

assert(boolean, message=nil)
  • booleanがtrueと評価されればテストは成功。
  • booleanがfalseまたはnilの場合にテストは失敗。
  • テストが失敗するとmessageが表示される。
  • messageは省略できる。
  • 1つのテストメソッドにassert(またはassert_xxxx)メソッドが複数ある場合は、最初に失敗したassertでそのテストメソッドは中断される。
class AssertTest < ActionController::IntegrationTest
  def test_assert
    assert false, "falseは想定外です"
    assert nil, "何らかの値が設定されるべきです"
  end
end
  1) Failure:
test_assert(AssertTest)
    [./test/integration/assert_test.rb:5:in `test_assert'
     /Library/Ruby/Gems/1.8/gems/actionpack-2.0.2/lib/action_controller/integration.rb:547:in `run']:
falseは想定外です.
 is not true.
  • テストメソッドが分かれていれば、失敗しても次のメソッドが実行されるので、連続して表示される。
class AssertTest < ActionController::IntegrationTest
  def test_assert1
    assert false, "falseは想定外です"
  end

  def test_assert2
    assert nil, "何らかの値が設定されるべきです"
  end
end
  1) Failure:
test_assert1(AssertTest)
    [./test/integration/assert_test.rb:5:in `test_assert1'
     /Library/Ruby/Gems/1.8/gems/actionpack-2.0.2/lib/action_controller/integration.rb:547:in `run']:
falseは想定外です.
 is not true.

  2) Failure:
test_assert2(AssertTest)
    [./test/integration/assert_test.rb:10:in `test_assert2'
     /Library/Ruby/Gems/1.8/gems/actionpack-2.0.2/lib/action_controller/integration.rb:547:in `run']:
何らかの値が設定されるべきです.
 is not true.

assert_XXXX

assert_difference(expressions, difference=1, message=nil) {ブロック}
否定形: assert_no_difference(expressions, message = nil) {ブロック}
  • expressionsは数値を返すRubyコードを文字列で指定する。
  • ブロックの最初と最後で、expressionsの式の結果に、differenceの差異が発生すれば成功。(否定形: expressionsの式の結果が変化しなければ成功)
# post :create,... の前後で、Slip.countが1増加すれば成功。
assert_difference('Slip.count') do
  post :create, {:slip   =>{:number=>'3', :executed_on=>'2/20', :total_yen=>'3000'}, 
                 :journal=>{"1"=>{:comment=>"test3", :yen=>"3000", :index=>"j943792543", :position=>"1"}}
                }
end
  • expressionsは、Rubyコード文字列を配列で複数指定することも可能。
# post :create,... の前後で、Slip.count + Journal.countが2増加すれば成功。
assert_difference(['Slip.count', 'Journal.count'], 2) do
  post :create, {:slip   =>{:number=>'3', :executed_on=>'2/20', :total_yen=>'3000'}, 
                 :journal=>{"1"=>{:comment=>"test3", :yen=>"3000", :index=>"j943792543", :position=>"1"}}
                }
end
assert_equal(expected, actual, message=nil)
否定形: assert_not_equal
  • expectedとactualが等しい時に成功する。(否定形: 等しくない時に成功する。)
  • expected は期待する値
  • actual はテスト対象の値
class AssertTest < ActionController::IntegrationTest
  def test_assert_equal
    a = [1,2,3]
    assert_equal 3, a.size, "配列の要素数が一致しません"
  end
end
  1) Failure:
test_assert_equal(AssertTest)
    [./test/integration/assert_test.rb:15:in `test_assert_equal'
     /Library/Ruby/Gems/1.8/gems/actionpack-2.0.2/lib/action_controller/integration.rb:547:in `run']:
配列の要素数が一致しません.
<2> expected but was
<3>.
assert_nil(object, message="")
否定形: assert_not_nil
  • objectがnilであるなら成功。(否定形: nilでない場合に成功。)
assert_match(pattern, string, message="")
否定形: assert_no_match
  • stringが正規表現patternにマッチすれば成功。(否定形: マッチしなければ成功。)
assert_in_delta(expected_float, actual_float, delta, message="")
  • 浮動小数点には誤差があるため、assert_equalの代わりに利用する。
  • expected_floatとactual_floatの差異がdelta以内なら成功する。(expected_float.to_f - actual_float.to_f).abs <= delta.to_f )
assert_raise(*expected_exception_klass, message="") {ブロック}
否定形: assert_nothing_raised
  • 「*expected_exception_klass」は「予想した例外」クラス。カンマで区切って複数指定できる。
  • ブロックを処理して「予想した例外」が、どれか一つ発生すれば成功。(否定形: 一つも発生しなければ成功。)
  • 否定形: assert_nothing_raisedで、「予想外の例外」が発生して、テストに成功した場合、Errorがカウントされる。
class AssertTest < ActionController::IntegrationTest
  def test_assert_rise
    assert_raise(RuntimeError, ArgumentError, "指定した例外が発生しません") {raise NoMethodError}
  end
  
  def test_assert_nothing_raised
    assert_nothing_raised(RuntimeError, ArgumentError, "例外が発生しました") {raise NoMethodError}
  end
end
  1) Error:
test_assert_nothing_raised(AssertTest):
NoMethodError: NoMethodError
    ./test/integration/assert_test.rb:25:in `test_assert_nothing_raised'
    ./test/integration/assert_test.rb:25:in `test_assert_nothing_raised'
    /Library/Ruby/Gems/1.8/gems/actionpack-2.0.2/lib/action_controller/integration.rb:547:in `run'

  2) Failure:
test_assert_rise(AssertTest)
    [./test/integration/assert_test.rb:21:in `test_assert_rise'
     /Library/Ruby/Gems/1.8/gems/actionpack-2.0.2/lib/action_controller/integration.rb:547:in `run']:
指定した例外が発生しません.
<[RuntimeError, ArgumentError]> exception expected but was
Class: 
Message: <"NoMethodError">
 ---Backtrace---
./test/integration/assert_test.rb:21:in `test_assert_rise'
./test/integration/assert_test.rb:21:in `test_assert_rise'
/Library/Ruby/Gems/1.8/gems/actionpack-2.0.2/lib/action_controller/integration.rb:547:in `run'
 ---------------
assert_valid(ActiveRecord_object)
  • ActiveRecord_objectの検証を実行して、エラーが無ければ成功。
slip = Slip.new(:number=>1, :total_yen=>1000)
assert_valid(slip)

コントローラー用のassert_XXXX

assert_response(type, message=nil)
assert_response :success
assert_response 200
assert_redirected_to(options={}, message=nil)
  • optionsが指定するURLオプションと、最後のアクションで呼び出されたリダイレクトのURLオプションが一致すれば成功。
assert_redirected_to :action=>'show'
assert_redirected_to 'http://localhost:3002/slips/1'
assert_template(expected, message=nil)
  • expectedが指定するビューテンプレートを利用して描画されたら成功。
assert_template 'new'
assert_select