Bar*_*rtD 31 python testing nose
我用鼻子测试异常.这是一个例子:
def testDeleteUserUserNotFound(self):
"Test exception is raised when trying to delete non-existent users"
try:
self.client.deleteUser('10000001-0000-0000-1000-100000000000')
# make nose fail here
except UserNotFoundException:
assert True
Run Code Online (Sandbox Code Playgroud)
如果引发异常,则执行assert,但如果没有引发异常,则不会执行.
我可以在上面的注释行中添加任何内容,以便如果没有异常,则会报告失败吗?
小智 46
nose提供了测试异常的工具(比如unittest).试试这个例子(并阅读Nose Testing Tools的其他工具
from nose.tools import *
l = []
d = dict()
@raises(Exception)
def test_Exception1():
'''this test should pass'''
l.pop()
@raises(KeyError)
def test_Exception2():
'''this test should pass'''
d[1]
@raises(KeyError)
def test_Exception3():
'''this test should fail (IndexError raised but KeyError was expected)'''
l.pop()
def test_Exception4():
'''this test should fail with KeyError'''
d[1]
Run Code Online (Sandbox Code Playgroud)
我认为这是您正在寻找的正确方法,因为它可以让您具体了解您期望或想要的异常.所以你实际上引发了错误,看到它引发了正确的异常.然后你让鼻子评估结果.(尽可能少地将逻辑放入单元测试中!)
Lou*_*uis 10
我强烈建议使用assert_raises和assert_raises_regexp来自nose.tools,复制行为assertRaises和assertRaisesRegexp来自unittest.TestCase.这些允许使用与unittest.TestCase实际不使用unittest.TestCase该类的测试套件中提供的功能相同的功能.
我发现这@raises是一种非常钝的乐器.以下是说明问题的代码:
from nose.tools import *
something = ["aaa", "bbb"]
def foo(x, source=None):
if source is None:
source = something
return source[x]
# This is fine
@raises(IndexError)
def test1():
foo(3)
# This is fine. The expected error does not happen because we made
# a mistake in the test or in the code. The failure indicates we made
# a mistake.
@raises(IndexError)
def test2():
foo(1)
# This passes for the wrong reasons.
@raises(IndexError)
def test3():
source = something[2] # This is the line that raises the exception.
foo(10, source) # This is not tested.
# When we use assert_raises, we can isolate the line where we expect
# the failure. This causes an error due to the exception raised in
# the first line of the function.
def test4():
source = something[2]
with assert_raises(IndexError):
foo(10, source)
Run Code Online (Sandbox Code Playgroud)
test3传递,但不是因为foo已经引发了我们期望的异常,而是因为设置要使用的数据的代码foo失败并具有相同的异常.test4展示如何使用assert_raises实际测试我们的测试意义来编写测试.第一行的问题会导致Nose报告错误,然后我们可以重写测试以便我们可以最终测试我们测试的意思.
@raises不允许测试与异常关联的消息.当我举起时ValueError,举一个例子,我通常想用一条信息性的信息来提高它.这是一个例子:
def bar(arg):
if arg: # This is incorrect code.
raise ValueError("arg should be higher than 3")
if arg >= 10:
raise ValueError("arg should be less than 10")
# We don't know which of the possible `raise` statements was reached.
@raises(ValueError)
def test5():
bar(10)
# Yes, we're getting an exception but with the wrong value: bug found!
def test6():
with assert_raises_regexp(ValueError, "arg should be less than 10"):
bar(10)
Run Code Online (Sandbox Code Playgroud)
test5哪些用途@raises会通过,但它会通过错误的原因.test6进行更精细的测试,揭示ValueError凸起不是我们想要的.
def testDeleteUserUserNotFound(self):
"Test exception is raised when trying to delete non-existent users"
try:
self.client.deleteUser('10000001-0000-0000-1000-100000000000')
assert False # <---
except UserNotFoundException:
assert True
Run Code Online (Sandbox Code Playgroud)
try/ except暗示执行流程将语句留在try异常上的语义,因此assert False如果引发异常则不会运行.此外,try在except块运行完毕后,执行不会再次重新进入块,因此您不应该遇到麻烦.
?
(statements)
? exception
(try) ???????????? (except)
? ?
(statements) ?????????????
?
Run Code Online (Sandbox Code Playgroud)
我不知道为什么它还没有到这里,但又存在一种方式:
import unittest
class TestCase(unittest.TestCase):
def testKeyError(self):
d = dict()
with self.assertRaises(KeyError):
d[1]
Run Code Online (Sandbox Code Playgroud)