2012-09-20 15 views
10

我有以下測試代碼檢查函數中引發異常。我期望測試通過,但是會指出失敗。下面是測試代碼:assertRaises失敗,即使可調用引發所需的異常(python,unitest)

import unittest 

# define a user-defined exception 
class MyException(Exception): 
    def __str__(self): 
     return repr("ERROR: Just raised my exception!") 

# this is my main class with a method raising this exception 
class MyMainObject(object): 

    def func(self): 
     raise MyException() 

# the test class 
class TestConfig(unittest.TestCase): 

    def test_1(self): 

     other = MyMainObject() 
     self.assertRaises(MyException, other.func()) 

# calling the test 
if __name__ == '__main__':  
    unittest.main() 

other.func()是所謂的斷言語句,MyException提高(可以很容易地進行檢查)。所以,assertRaises測試應該通過測試,如other.func() failes與MyException,但:

.... 
MyException: 'ERROR: Just raised my exception!' 

---------------------------------------------------------------------- 
Ran 1 test in 0.001s 

FAILED (errors=1) 

我看不出什麼問題,所以我希望在這個問題上的一些輸入。

+1

您應該注意到這是一個錯誤,而不是失敗!你的例外甚至沒有被捕獲。 –

回答

17

assertRaises調用函數爲您服務。通過自己調用它,除了assertRaises可以對其進行測試之前,將異常提出

你的代碼更改爲:

self.assertRaises(MyException, other.func) 

,它會正常工作。另外,您也可以使用assertRaises作爲一個上下文管理器(Python 2.7版以上):

with self.assertRaises(MyException): 
    other.func() 

使用assertRaises作爲上下文經理有額外的好處,你現在可以檢索異常實例並在其上進行進一步的測試:

with self.assertRaises(MyException) as raises_cm: 
    other.func() 

exception = raises_cm.exception 
self.assertEqual(exception.args, ('foo', 'bar')) 
+0

我知道這很簡單。也許我應該在另一天看...(等待2分鐘,直到我可以點擊鉤子) – Alex

+0

@Alex不要覺得太糟糕 - 我認爲這更像是單元測試不直觀的問題 - 其他測試框架按照您的預期工作。 – mikemaccana

+0

我在pycharm IDE中使用python 3.3解釋器。如果我想將參數傳遞給被測試的函數,並且還包含一條消息以防萬一不出現所需的錯誤,該怎麼辦?示例 - 'self.assertRaises(ValueError,person.set_age_method,-10,「Error:Person's age can not be negative。」)這樣,我得到一個異常:'set_age_method需要2個位置參數,但是有3個被給定。我該如何解決 ?順便說一句,這個斷言的文檔沒有明確告訴你如何去做。 https://docs.python.org/3/library/unittest.html#unittest.TestCase.assertRaises。什麼是kwds? – testerjoe2

7

由於語言的規則,參數在被調用函數的代碼被輸入之前被評估(這通常是件好事)。因此,在評估參數期間,assertRaises無法捕獲發生的異常。解決方法(在多個API中)是你將可調用的傳遞給assertRaises等方法,以便他們可以在他們可以控制的位置以及他們可以捕獲異常的位置對其進行評估。如果整個參數是一個方法調用的綁定方法的魔力可以讓你說出這個相當漂亮,沒有lambda或如愚蠢:

self.assertRaises(MyException, other.func) # <- note, no parentheses after func 
+0

我在pycharm IDE中使用python 3.3解釋器。如果我想將參數傳遞給被測試的函數,並且還包含一條消息以防萬一不出現所需的錯誤,該怎麼辦?示例 - 'self.assertRaises(ValueError,person.set_age_method,-10,「Error:Person's age can not be negative。」)這樣,我得到一個異常:'set_age_method需要2個位置參數,但是有3個被給定。我該如何解決 ?順便說一句,這個斷言的文檔沒有明確告訴你如何去做。 https://docs.python.org/3/library/unittest.html#unittest.TestCase.assertRaises。什麼是kwds? – testerjoe2

+1

@ testerjoe2函數後面的所有內容,包括像'age = -10'這樣的關鍵字參數(這是'** kwds'代表的內容)被傳遞給可調用對象。你應該直接創建'ValueError'對象,因爲它的構造不需要像函數調用一樣被延遲(如果你不'提升'它們,異常對象是無害的),所以你想要:'self.assertRaises(ValueError (「錯誤:人的年齡不能爲負數」),person.set_age_ethod,-10)'。 – delnan

相關問題