2013-07-24 4 views
1

Использование MiniTest спецификации, я могу проверить, что код вызывает определенное исключение следующим образом:Проверка любого исключения

proc { foo.do_bar }.must_raise SomeException 

Но, я не волнует, что конкретное исключение, я просто хочу, чтобы убедиться, что часть исключение бросается. Если я или другой разработчик решает изменить, какое исключение выбрано Foo # do_bar, мой тест не изменился бы, если бы ожидаемое исключение было указано в целом достаточно.

То есть, я хотел бы написать тест таким образом (исключение является предком класса SomeException):

proc { foo.do_bar }.must_raise Exception 

К этому приводит к сбою при запуске теста:

[Exception] exception expected, not 
Class: <SomeException> 

Могу ли я написать свою спецификацию Minitest более универсально в отношении исключений?

(Фактическая причина, по которой я хочу проверить любое исключение, а не конкретное исключение, заключается в том, что я использую сторонний Gem, и именно этот код вызывает исключение. Фактически, мой метод A получает вызванный сторонним методом B. A вызывает MyException, однако B улавливает это исключение и повторно вызывает другое исключение. Это исключение имеет то же сообщение, что и мое исключение [и это сообщение - это то, что я должен проверить в тесте], но другой класс.)

+1

Так что вам все равно, было ли это 'SystemStackError' или' SystemExit' или 'ThreadError'? Тогда зачем тестировать? Вы должны проверить специфику. В противном случае, как вы сообщаете другим разработчикам, каковы были ваши намерения? – vgoff

+0

@vgoff: Для краткости я оставил это, но я работаю с Ruby Racer, который связывает JavaScript с Ruby и наоборот. Если мой код Ruby вызывает исключение, это исключение заканчивается как RR-класс, V8 :: Error, а не исключение, которое вызвал мой код.Это связано с внутренними данными стороннего Gem, которые я использую, и это детали, которые меня не интересуют с точки зрения тестирования или даже с точки зрения реализации. С точки зрения тестирования важно то, что мой код Ruby обнаруживает недопустимое условие, и возникает исключение. – Jimothy

+0

@vgoff Пока он меняет «почему», он не меняет «как», насколько я могу судить. Вы поднимаете хороший момент со своим первым комментарием, в общем, нужно быть конкретным во время тестирования. Тем не менее, я не хочу задавать свой вопрос чрезмерно конкретным, так как могут быть и другие, которые по какой-либо причине хотят протестировать любое исключение с помощью MiniTest. Однако я добавлю пояснительный текст к своему вопросу, почему я хотел бы это сделать. – Jimothy

ответ

2
describe 'testing' do 
    it 'must raise' do 
    a = Proc.new {oo.non_existant} 
    begin 
    a[] 
    rescue => e 
    end 
    e.must_be_kind_of Exception 
    end 
end 

Независимо от того, что это должно сделать довольно близко к тому, о чем вы просите.

0

Это кажется странным поведением.

От: http://bfts.rubyforge.org/minitest/MiniTest/Assertions.html#method-i-assert_raises

# File lib/minitest/unit.rb, line 337 
def assert_raises *exp 
    msg = "#{exp.pop}\n" if String === exp.last 

    should_raise = false 
    begin 
    yield 
    should_raise = true 
    rescue MiniTest::Skip => e 
    details = "#{msg}#{mu_pp(exp)} exception expected, not" 

    if exp.include? MiniTest::Skip then 
     return e 
    else 
     raise e 
    end 
    rescue Exception => e 
    details = "#{msg}#{mu_pp(exp)} exception expected, not" 
    assert(exp.any? { |ex| 
      ex.instance_of?(Module) ? e.kind_of?(ex) : ex == e.class 
      }, exception_details(e, details)) 

    return e 
    end 

    exp = exp.first if exp.size == 1 
    flunk "#{msg}#{mu_pp(exp)} expected but nothing was raised." if 
    should_raise 
end 

Это проверяет исключение передается является экземпляром Module и если да использует e.kind_of?(ex), который будет работать нормально, как в качестве экземпляра SomeException будет доброй Exception, но только если ex является модуль , поэтому Exception не будет работать. Это должно быть что-то общее, что вы смешали с вашими исключениями.

(как показано здесь http://ruby-doc.org/core-2.0/Object.html#method-i-kind_of-3F)

Это соответствует minitests собственные тесты ...

module MyModule; end 
    class AnError < StandardError; include MyModule; end 

    .... 

    def test_assert_raises 
    @tc.assert_raises RuntimeError do 
     raise "blah" 
    end 
    end 

    def test_assert_raises_module 
    @tc.assert_raises MyModule do 
     raise AnError 
    end 
    end 

(От: https://github.com/seattlerb/minitest/blob/master/test/minitest/test_minitest_unit.rb)

Так .. если ваш Exception смешивает в модуле, вы может утверждать на модуле, но кроме этого, ответьте на ответ @ vgoff .. или увеличьте minitest, чтобы делать то, что вы хотите.

Примечание: Мне нравится, что рубин - это все с открытым исходным кодом!

Смежные вопросы