Search code examples
pythonpython-2.7nosetests

assert_raises() from nose tools doesn't really work


Ok, here is the problem: in exercise 49 of "Learn Python the Hard Way" by Zed Shaw, we need to test a couple of exceptions with assert_raises(). Here is the function, that I'm testing and if omitting the assert_raises() part, it passes the test:

def parse_verb(word_list):
    skip(word_list, 'stop')

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

Here is the test function and the infamous assert_raises() line:

def parse_verb_test():
    vrb_list = [('of', 'stop'), ('from', 'stop'), ('go', 'verb'), ('north', 'direction')]
    assert_equal(parse_verb(vrb_list), ('go', 'verb'))
    assert_equal(vrb_list, [('north', 'direction')])
    assert_raises(ParserError, parse_verb, vrb_list)

And it gives me the following output:

.........E...
======================================================================
ERROR: tests.parser_tests.parse_verb_test
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/nose/case.py", line 197, in runTest
    self.test(*self.arg)
  File "/Users/vsevolod/Repositories/ex48/tests/parser_tests.py", line 20, in parse_verb_test
    assert_raises(ParserError, parse_verb, vrb_list)
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/unittest/case.py", line 471, in assertRaises
    callableObj(*args, **kwargs)
  File "/Users/vsevolod/Repositories/ex48/ex48/parser.py", line 40, in parse_verb
    raise ParserError("Expected a verb next.")
TypeError: object.__new__() takes no parameters

----------------------------------------------------------------------
Ran 13 tests in 0.042s

FAILED (errors=1)

I also tried getting rid of the assert_raises() line and using the @raises(ParserError) before the function. It also didn't quite work and resulted in the same output.

Creating a separate test like this helped to get rid of the error:

def parse_verb_fail():
    fail_list = [('north', 'direction'), ('go', 'verb')]
    assert_raises(ParserError, parse_verb, fail_list)

But now the test is simply ignored.

What am I doing wrong?


Solution

  • I believe your problem is that ParserError doesn't have a constructor that takes a string (or ParserError doesn't extend from Exception and is trying to pass a string to the base object's init method...). So when you try and create ParserError you are getting a TypeError and not a ParserError. Since your assert_raises() wasn't expecting a TypeError it doesn't catch it.

    EDIT:

    Looking at the example code you linked to and playing around. Are you sure you have...

    class ParserError(Exception): pass
    

    ...and not...

    class ParserError(object): pass