Подтвердить что ты не робот

Почему у MiniTest:: Spec нет утверждения wont_raise?

Ruby Test::Unit имеет assert_nothing_raised. Test::Unit был заменен на MiniTest. Почему утверждения MiniTest/ожидания не имеют ничего подобного? Например, вы можете ожидать must_raise, но не wont_raise.

4b9b3361

Ответ 1

MiniTest реализует assert_nothing_raised на своем уровне совместимости с Test:: Unit, но в своих собственных тестах (MiniTest::Unit и MiniTest::Spec) он не выполняет никаких подобных тестов. Причина в том, что программист утверждает, что тестирование для ничего поднятого не является чем-либо тестированием; вы никогда не ожидаете, что что-либо будет поднято в тесте, за исключением случаев, когда вы тестируете исключение. Если в коде для теста возникает непредвиденное (неперехваченное) исключение, вы получите сообщение об ошибке, указанное в хорошем порядке, и вы узнаете, что у вас есть проблема.

Пример:

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/70

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 никогда не отвечал за это.

Ответ 2

Если вам это нужно:

# 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

Ответ 3

Это беспокоило меня достаточно, чтобы вникнуть в источники 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. Ура!:)