RubyのTest::Unit
にはassert_nothing_raised
があります。 Test::Unit
は MiniTest に置き換えられました。 MiniTestのアサーション/期待がこれに類似していないのはなぜですか?たとえば、must_raise
は期待できますが、wont_raise
は期待できません。
MiniTestはTest :: Unit互換性レイヤーにassert_nothing_raised
を実装しますが、独自のテスト(MiniTest::Unit
およびMiniTest::Spec
)では実装しませんnotこのようなテストを実装します。その理由は、プログラマーは、何も起こらなかった場合のテストは何のテストでもないと主張しているからです。 for例外をテストしている場合を除いて、テストで何かが発生することを決して期待しません。テストのコードで予期しない(捕捉されなかった)例外が発生した場合、テストによって適切な順序で例外が報告され、問題があることがわかります。
例:
require 'minitest/autorun'
describe "something" do
it "does something" do
Ooops
end
end
出力:
Run options: --seed 41521
# Running tests:
E
Finished tests in 0.000729s, 1371.7421 tests/s, 0.0000 assertions/s.
1) Error:
test_0001_does_something(something):
NameError: uninitialized constant Ooops
untitled:5:in `block (2 levels) in <main>'
1 tests, 0 assertions, 0 failures, 1 errors, 0 skips
それはまさにあなたが知りたかったことです。何も起こらないと期待していたのなら、それは得られず、そう言われました。
したがって、ここでの議論は次のとおりです。assert_nothing_raised
を使用しないでください!それはただの無意味な松葉杖です。たとえば、次を参照してください。
https://github.com/seattlerb/minitest/issues/7
https://github.com/seattlerb/minitest/issues/159
http://blog.zenspider.com/blog/2012/01/assert_nothing_tested.html
一方、assert_nothing_raised
はwont_raise
と一緒に行くことを期待する人が非常に多いため、明らかにmust_raise
はユーザーの直感に対応します。特にこれに対するアサーションは、単なるテストではありません。幸い、MiniTestは非常にミニマリストで柔軟性があるため、独自のルーチンを追加したい場合は可能です。したがって、例外がないかどうかをテストし、例外がない場合は既知の結果を返すメソッドを作成できます。これで、その既知の結果をアサートできます。
たとえば(これが完璧だと言っているのではなく、アイデアを示しているだけです):
class TestMyRequire < MiniTest::Spec
def testForError # pass me a block and I'll tell you if it raised
yield
"ok"
rescue
$!
end
it "blends" do
testForError do
something_or_other
end.must_equal "ok"
end
end
重要なのは、これが良いアイデアでも悪いアイデアでもないということではなく、MiniTestがあなたに代わってそれを行う責任は決してないということです。
必要な場合:
# test_helper.rb
module Minitest::Assertions
def assert_nothing_raised(*)
yield
end
end
そしてそれを使用するには:
def test_unknown_setter
assert_nothing_raised do
result.some_silly_column_name = 'value'
end
end
これは、MiniTestソースを掘り下げて、spec_helper.rb
ファイルに実装を提供するのに十分な気になりました。
module MiniTest
module Assertions
def refute_raises *exp
msg = "#{exp.pop}.\n" if String === exp.last
begin
yield
rescue MiniTest::Skip => e
return e if exp.include? MiniTest::Skip
raise e
rescue Exception => e
exp = exp.first if exp.size == 1
flunk "unexpected exception raised: #{e}"
end
end
end
module Expectations
infect_an_assertion :refute_raises, :wont_raise
end
end
これがwont_raise
を必要とする他の誰かに役立つことを願っています。乾杯! :)