12

Learn Ruby theHardWayの演習49に取り組んでいます

演習では、提供されている関数ごとに単体テストを作成するように求められます。私がテストしている項目の1つは、適切な例外が発生したかどうかです。assert_raiseこの目的で使用することをお勧めします。

これが私がテストしているコードです:

class ParserError < Exception

end

Pair = Struct.new(:token, :word)

def peek(word_list)
    begin
        word_list.first.token
    rescue
        nil
    end 
end

def match(word_list, expecting)
    word = word_list.shift
    if word.token == expecting
        word
    else
        nil
    end
end

def skip_word(word_list, token)
    while peek(word_list) == token
        match(word_list, token)
    end
end

def parse_verb(word_list)
    skip_word(word_list, :stop)

    if peek(word_list) == :verb
        return match(word_list, :verb)
    else
        raise ParserError.new("Expected a verb next.")
    end
end

そして、これが関数parse_verbのテストです。

def test_parse_verb
    list_one = [Pair.new(:verb, 'go'), Pair.new(:noun, 'king')]
    assert_equal(parse_verb(list_one), Pair.new(:verb, 'go'))

    list_two = [Pair.new(:noun, 'player') ,Pair.new(:verb, 'go'), Pair.new(:noun, 'king')]
    assert_raise(ParserError.new("Expected a verb next.")) {parse_verb(list_two)}
end

テストを実行すると失敗し、次のメッセージが表示されます。

Larson-2:test larson$ ruby test_sentence.rb
Loaded suite test_sentence
Started
.F..
Finished in 0.001204 seconds.

  1) Failure:
test_parse_verb(SentenceTests) [test_sentence.rb:36]:
[#<ParserError: Expected a noun or direction next.>] exception expected, not
Class: <ParserError>
Message: <"Expected a verb next.">
---Backtrace---
/Users/larson/Ruby/projects/ex48/lib/sentence.rb:45:in `parse_verb'
test_sentence.rb:36:in `block in test_parse_verb'
---------------

4 tests, 7 assertions, 1 failures, 0 errors, 0 skips

Test run options: --seed 40627

私の機能の理解に基づいてassert_raise、このテストは合格するはずですが、私がそれを使用している方法に何か問題がありますか?

私が使用しているすべてのファイルの完全なソースコードが必要な場合は、ここから入手できます。

4

2 に答える 2

33

assert_raise必要な例外のインスタンスではなく、1つ以上の例外クラスをパラメーターとして予期します。

また、発生した例外を返すため、メッセージ(またはその他のプロパティ)をアサートする場合は、個別に行うことができます。したがって、置き換えてみてください:

assert_raise(ParserError.new("Expected a verb next.")) {parse_verb(list_two)}

と:

exception = assert_raise(ParserError) {parse_verb(list_two)}
assert_equal("Expected a noun or direction next.", exception.message) 
于 2011-09-04T10:12:50.073 に答える
2

何らかの理由で、上記の答えは私にはうまくいきませんでした(私はRuby2.0.0を使用しています)。

それが機能するためには、Errorクラス名を文字列でラップする必要があります。

assert_raise("RuntimeError") { 
    # some code to trigger the error
}
于 2013-10-02T02:36:22.603 に答える