7

的使用,我对Exercise 49 of Learn Ruby the Hard Way正确Assert_Raise单元测试和异常类

工作的练习要求写出所提供的每项功能的单元测试。我正在测试的项目之一是如果提出适当的例外。建议我们使用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函数的理解,这个测试应该通过,我使用它的方式有什么问题吗?

如果有人想所有文件的完整的源代码,我有我的工作是提供here

回答

28

assert_raise预计一个或多个异常类作为它的参数,而不是必需的例外的一个实例。

它也返回引发的异常,所以如果你想断言消息(或任何其他属性),你可以单独做。因此,尝试更换:

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) 
+0

感谢您的帮助!这解决了我的问题。 –

2

出于某种原因,上面给出的我没有工作了答案(我使用Ruby 2.0.0)。

我有一个字符串来包装错误的类名,它的工作:

assert_raise("RuntimeError") { 
    # some code to trigger the error 
}