2011-10-17 37 views
24

我用鼻子测试异常。下面是一个例子:我们应该如何用鼻子测试异常?

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 

如果引发异常,则执行断言,但如果没有引发异常,则不会执行断言。

有什么我可以把上面的评论线,以便如果没有例外引发鼻子会报告失败?

+0

差不多一个副本http://stackoverflow.com/questions/11767938/how-to-use-noses-assert-raises – Stefano

回答

39

鼻子提供工具,用于测试异常(比如单元测试一样)。 试试这个例子(在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] 

了解其他工具,我觉得这是你要找的人,因为它可以让你要具体说明您所期望或想要的例外有道所以你竟招来错误地看到,它提出的权利除外。然后你让鼻子评估结果。(把尽可能少的逻辑到单元测试越好!)

+4

谢谢。从外观上看,还有'assert_raises'。 – BartD

+2

鼻子也暴露了assert_raises,它只是self.assertRaises from unittest。当你需要对表单中的异常进行更多处理时,这一点很方便。与assertRaises(ValueError)为e:

1

我不知道鼻子是什么,但是你是否在except子句后面使用了'else'。即

else: 
    assert False 
8
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 

try/except的语义意味着执行流离开try块上的异常,所以如果assert False引发异常将不会运行。此外,在except块完成运行后,执行将不会再次重新输入try块,因此您不应该遇到麻烦。

 ↓ 
(statements) 
    ↓ exception 
    (try) ↚──────────→ (except) 
    ↓     │ 
(statements) ←───────────┘ 
    ↓ 
6

我不知道为什么这里还没有,但还有一种方式:

import unittest 

class TestCase(unittest.TestCase): 

    def testKeyError(self): 
     d = dict() 
     with self.assertRaises(KeyError): 
      d[1] 
+1

这个机制没有被提及,因为这篇文章是专门用鼻测试来测试的,它不需要'unittests.TestCase'中的类或继承的用户(定义'你提到的assertRaises方法)。 – PeterJCLaw

2

使用assert_raises

from nose.tools import assert_raises 

our_method   = self.client.deleteUser 
arg1    = '10000001-0000-0000-1000-100000000000' 
expected_exception = UserNotFoundException 

assert_raises(expected_exception, our_method, arg1) 

使用try和catch在你的测试好像不好的做法(大多数情况下)。

有在鼻子没有具体的文件,因为它基本上只是围绕unittest.TestCase.assertRaises(REF。How to use nose's assert_raises?)的包装

4

我强烈建议使用从nose.toolsassert_raisesassert_raises_regexp,其中重复的assertRaisesunittest.TestCaseassertRaisesRegexp行为。这些允许在测试套件中使用与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) 

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) 

test5它采用@raises会过去,但它会通过对错误的原因。 test6执行更精细的测试,显示ValueError提出的不是我们想要的。

相关问题