来自nose工具的assert_raises()并不真正起作用

时间:2013-04-24 12:51:05

标签: python python-2.7 nosetests

好的,问题是:在Zed Shaw的“学习Python困难之路”的exercise 49中,我们需要使用assert_raises()测试几个例外。这是我正在测试的函数,如果省略assert_raises()部分,它会通过测试:

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.")

这是测试功能和臭名昭着的assert_raises()行:

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)

它给了我以下输出:

.........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)

我还试图摆脱assert_raises()行并在函数前使用@raises(ParserError)。它也没有完全奏效并产生相同的输出。

创建这样的单独测试有助于摆脱错误:

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

但现在测试被忽略了。

我做错了什么?

2 个答案:

答案 0 :(得分:5)

我相信你的问题是ParserError没有一个带字符串的构造函数(或ParserError没有从Exception扩展并尝试将字符串传递给基础对象的init方法......)。因此,当您尝试创建ParserError时,您将获得TypeError而不是ParserError。由于您的assert_raises()没有预料到TypeError,因此无法捕捉到它。

编辑:

查看您链接到并播放的示例代码。你确定你有......

class ParserError(Exception): pass

......而不是......

class ParserError(object): pass

答案 1 :(得分:0)

Zed Shaw的“学习Python困难之路”仍然是一个很好的资源,所以也许我的贡献会有所帮助。

忽略parse_verb_fail函数的原因是,鼻子测试函数的名称必须带有“ test_”,或者如documentation更完整地说明:

  

默认情况下,任何与已配置的testMatch正则表达式((?:^ | [\ b _ \ .-])[Tt] est相匹配的函数或类-即在单词边界或在-之后具有test或Test或_),并且位于与该表达式匹配的模块中,该模块将作为测试运行。

这是我有效的解决方案:

def test_parse_errors():
    subject_fail_list = [('stop', 'the'), ('direction', 'north')]
    assert_raises(parser.ParseError, parser.parse_subject, subject_fail_list)

nose将运行此测试,并且将通过。将其中一个元组更改为('noun','john')会导致测试失败,因为parse_subject正在寻找'noun'。