我在Python中练习TDD,并在测试是否引发异常时遇到了问题。
以下test_phonebook.py
test_add_empty_name_raises_exception
失败。
import unittest
import phonebook
class Test(unittest.TestCase):
def test_add_empty_name_raises_exception(self):
self.assertRaises(ValueError, phonebook.add, "", "1111111111")
if __name__ == "__main__":
# import sys;sys.argv = ['', 'Test.testName']
unittest.main()
以下是我的phonebook.py
方法add
,它将数据添加到词典中。
import re
_phonebook = {}
file_name = "phonebook.txt"
def is_valid_name(name):
return re.search(r"([A-Z][a-z]*)([\\s\\\'-][A-Z][a-z]*)*", name) is not None
def is_valid_number(number):
return re.search(r"\+?[\d ]+$", number) is not None
def add(name, number):
try:
if is_valid_name(name) and is_valid_number(number):
_phonebook[name] = number
else:
raise ValueError("Invalid arguments.", name, number)
except ValueError as err:
print err.args
if __name__ == '__main__':
pass
我的问题是,即使在控制台日志中看到ValueError
方法中出现了add
,测试也会失败。
Finding files... done.
Importing test modules ... done.
('Invalid arguments.', '', '1111111111')
======================================================================
FAIL: test_add_empty_name_raises_exception (path.to.phonebook.test_phonebook.Test)
----------------------------------------------------------------------
Traceback (most recent call last):
File "path\to\phonebook\test_phonebook.py", line 13, in test_add_empty_name_raises_exception
self.assertRaises(ValueError, phonebook.add, "", "1111111111")
AssertionError: ValueError not raised
----------------------------------------------------------------------
Ran 1 test in 0.002s
我该如何解决这个问题?我有遗忘的东西吗?
我也尝试在Python 2.7中使用新格式处理测试中的异常,但它仍然没有引起ValueError
的提升。
def test_add_empty_name_raises_exception(self):
with self.assertRaises(ValueError):
self.phonebook.add("", "1111111111)
我还将测试用例的形式更改为使用lambdas,但仍然没有更改。
def test_add_empty_name_raises_exception(self):
self.assertRaises(ValueError, lambda: phonebook.add("", "1111111111"))
我还清理了我的目录并重新启动了Eclipse Luna,问题仍然存在。
可能的解决方案
我正在阅读8.Errors and Exceptions文档并进入" Raising Exceptions"部分说明:
If you need to determine whether an exception was raised but don’t intend to handle it,
a simpler form of the raise statement allows you to re-raise the exception:
我将此添加到现有的add
方法中:
def add(name, number):
try:
if is_valid_name(name) and is_valid_number(number):
_phonebook[name] = number
print "Added %s:\t%s" % (name, number)
else:
raise ValueError("Invalid arguments.", name, number)
except ValueError as err:
print err.args
raise
导致测试用例通过。
这是正确的方法吗?要在raise
区块再次致电except
吗?
答案 0 :(得分:2)
当您捕获异常(在except ValueError as err:
块中)时,会阻止它继续备份调用堆栈以最终终止程序。从本质上讲,你说'#34;我知道如何处理这个问题,所以不需要恐慌其他人。"
重新引发异常是正确的做法,如果您发现了异常,但没有这样做以实际修复任何事情,例如,记录它发生的事情。但是,通常情况下,人们会捕获异常以便纠正它。
在您的情况下,您自己提出异常后几乎立即捕获异常。为什么不将您的日志记录语句放在与else
相同的raise
块中?根本不需要try: ... except:
缩进。
def add(name, number):
if is_valid_name(name) and is_valid_number(number):
_phonebook[name] = number
print "Added %s:\t%s" % (name, number)
else:
print "Invalid arguments.", name, number
raise ValueError("Invalid arguments.", name, number)
return