Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Proper Assert_Raise Unit Testing and Use of Exception Class

I am working on Exercise 49 of Learn Ruby the Hard Way

The exercise asks to write a unit test for each function provided. One of the items I am testing is if a proper exception is raised. It is suggested that we use assert_raise for this purpose.

Here is the code I am testing:

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

And here is the test, for the function 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

When I run the test, it fails and here is the message I get:

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

Based on my understanding of the assert_raise function, this test should pass, is there something wrong with the way I am using it?

If anybody would like a full source code of all the files I am working with I it is available here

like image 925
Andrew Lauer Barinov Avatar asked Sep 04 '11 00:09

Andrew Lauer Barinov


People also ask

What is Assert_raise?

assert_raise(exception, function) Asserts the exception is raised during function execution. Returns the rescued exception, fails otherwise. assert_raise(exception, message, function) Asserts the exception is raised during function execution with the expected message , which can be a Regex or an exact String .

How do you handle exceptions in unit test Python?

There are two ways you can use assertRaises: using keyword arguments. Just pass the exception, the callable function and the parameters of the callable function as keyword arguments that will elicit the exception. Make a function call that should raise the exception with a context.


1 Answers

assert_raise expects one or more exception classes as its parameters, rather than an instance of the required exception.

It also returns the exception raised so if you want to assert the message (or any other properties) you can do that separately. So try replacing:

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

with:

exception = assert_raise(ParserError) {parse_verb(list_two)}
assert_equal("Expected a noun or direction next.", exception.message) 
like image 96
Steve Avatar answered Oct 01 '22 19:10

Steve