2011-10-17 34 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提出的不是我們想要的。

相關問題