Python 从nose tools(';真的不行

Python 从nose tools(';真的不行,python,python-2.7,nosetests,Python,Python 2.7,Nosetests,好的,问题是:在Zed Shaw的“艰苦学习Python”一书中,我们需要使用assert\u raises()测试几个异常。这是我正在测试的函数,如果省略assert\u raises()部分,它将通过测试: def parse_verb(word_list): skip(word_list, 'stop') if peek(word_list) == 'verb': return match(word_list, 'verb') else:

好的,问题是:在Zed Shaw的“艰苦学习Python”一书中,我们需要使用
assert\u raises()
测试几个异常。这是我正在测试的函数,如果省略
assert\u 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.")
下面是test函数和臭名昭著的
assert\u 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\u raises()
行,并在函数之前使用
@raises(parserror)
。它也没有很好的工作,并导致相同的输出

创建这样一个单独的测试有助于消除错误:

def parse_verb_fail():
    fail_list = [('north', 'direction'), ('go', 'verb')]
    assert_raises(ParserError, parse_verb, fail_list)
但是现在这个测试被完全忽略了


我做错了什么?

我相信您的问题是
parserror
没有接受字符串的构造函数(或者
parserror
没有从
Exception
扩展,并试图将字符串传递给基对象的init方法…)。因此,当您尝试创建
parserror
时,您得到的是
TypeError
,而不是
parserror
。由于您的
assert\u raises()
不希望出现
TypeError
错误,因此它无法捕获该错误

编辑:

查看链接到的示例代码,并进行演示。你确定你有

class ParserError(Exception): pass
…而不是

class ParserError(object): pass

我相信您的问题是
parserror
没有接受字符串的构造函数(或者
parserror
没有从
Exception
扩展,并且正在尝试将字符串传递给基对象的init方法…)。因此,当您尝试创建
parserror
时,您得到的是
TypeError
,而不是
parserror
。由于您的
assert\u raises()
不希望出现
TypeError
错误,因此它无法捕获该错误

编辑:

查看链接到的示例代码,并进行演示。你确定你有

class ParserError(Exception): pass
…而不是

class ParserError(object): pass

Zed Shaw的《艰苦学习Python》仍然是一个很好的资源,因此我的贡献可能会有所帮助

parse_verb_fail函数被忽略的原因是nose test函数的名称中必须有“test_”,或者如更完整的说明:

任何与配置的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'。

Zed Shaw的《艰苦学习Python》仍然是一个很好的资源,因此我的贡献可能会有所帮助

parse_verb_fail函数被忽略的原因是nose test函数的名称中必须有“test_”,或者如更完整的说明:

任何与配置的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'。

调试一个测试时,我通常建议的第一件事是,每个测试只能有一个assert。为什么?如果三个(在您的案例中)中的一个失败,那么其他的将不会运行,因此您实际创建的是资产之间的依赖关系。我认为,如果重构测试,这将自行解决问题。将
assert\u raises()
移动到单独的
verb\u parser\u fail
测试确实有助于消除错误,但现在它只是忽略了测试。它仍然输出已经通过了13个测试,等等,对测试进行注释并不会减少这个数字。看起来您得到的异常不是您期望的异常(是
TypeError
而不是
ParseError
)。您的
parserror
类型定义是否正确?在调试测试时,我通常建议的第一件事是,每个测试只能有一个assert。为什么?如果三个(在您的案例中)中的一个失败,那么其他的将不会运行,因此您实际创建的是资产之间的依赖关系。我认为,如果重构测试,这将自行解决问题。将
assert\u raises()
移动到单独的
verb\u parser\u fail
测试确实有助于消除错误,但现在它只是忽略了测试。它仍然输出已经通过了13个测试,等等,对测试进行注释并不会减少这个数字。看起来您得到的异常不是您期望的异常(是
TypeError
而不是
ParseError
)。您的
parserror
类型定义是否正确?是!在最初的测试中,我尝试将其更改为
TypeError
,结果它顺利通过了测试。然后我将
parserror
的父级更改为
Exception
,它也起了作用。非常感谢。在Zed Shaw给出的代码片段中,这部分包含
Exception
作为
parserror
的父级的代码甚至被标记为红色,我不知道我怎么会错过它。该死,佩斯比我快了。通常,@vsevologlumov,异常是异常的(通常是间接的)子类。Python不强制执行异常层次结构(“同意的成年人”),但几乎所有代码都遵循它。是的!在最初的测试中,我尝试将其更改为
TypeError
,结果它顺利通过了测试。然后我将
parserror
的父级更改为
Exception
,它也起了作用。非常感谢。此部分的
异常
解析器错误
的父级,甚至在代码片段中标记为红色