2015-11-05 59 views
0

我有以下代碼:如何assertRaises一個特定的異常

def foo(input): 
    if not input.startswith("prefix"): 
     raise Exception("input should start with prefix!") 
    process(input) 

現在我想單元測試這個功能;當input不是以"prefix"開頭時,它實際上可能會拋出異常。這裏是我的unittest代碼:

def test_foo_invalud_type(self): 
    self.assertRaises(Exception, foo, 999) 

與這個測試代碼的問題是:它捕獲了異常,但例外的是'int' object has no attribute 'startswith',而不是input should start with prefix!。測試會通過,但這不是一個好的測試。我如何識別兩個例外?

回答

4

raise Exception是非常糟糕的形式 - 嘗試在引發異常時更具體。使用這樣的一般異常使得你很難區分你想要測試的兩種不同情況。

在這種情況下,例如,我認爲ValueError會內foo是最合適的,因爲它是事情的正確類型(一個字符串),但沒有正確的價值(不'prefix'在開始)。

def foo(input): 
    if not input.startswith("prefix"): 
     raise ValueError("input should start with prefix!") 
    process(input) 

這讓你輸入的類型之間進行區分是錯的(這引起了一個AttributeError由於不存在的.startswith *):

def test_foo_invalid_type(self): # note fixed typo in 'invalud' 
    self.assertRaises(AttributeError, foo, 999) # and more specific error 

和輸入的ValueError明確提出缺少'prefix'前綴):

def test_foo_invalid_value(self): 
    with self.assertRaises(ValueError) as cm: 
     foo('no prefix') 
     self.assertEqual(
      cm.exception.args, 
      ('input should start with prefix!',), 
     ) 

請注意如何使用with上下文管理器形式assertRaises來訪問錯誤本身。這使您還可以檢查是否爲錯誤提供了正確的消息。


*您甚至可以考慮處理AttributeErrorfoo,提高一個TypeError代替。這似乎更適合於「該參數是錯誤的類型」

+0

我認爲我誤解了這個問題至少兩次,但我現在對此感到高興...... – jonrsharpe

+0

謝謝。我不得不承認我的問題是一個不好的描述。 – Suanmeiguo

1

你正在向函數foo傳遞一個int,但它看起來像你想要一個str(因爲你在參數input上使用startswith)。單元測試應該是:

def test_foo_invalud_type(self): 
    self.assertRaises(Exception, foo, '999') 
0

是提高誤差線是:

if not input.startswith("prefix"): 

而不是:

raise Exception("input should start with prefix!") 

因爲你傳遞一個int,而不是字符串:999而不是'999'

請記住int,沒有屬性startswith。

0

只需執行並引發您自己的異常。

class BadStartException(Exception): 
    pass 

def foo(input): 
    if not input.startswith("prefix"): 
     raise BadStartException("input should start with prefix!") 
    process(input) 

def test_foo_invalud_type(self): 
    self.assertRaises(BadStartException, foo, 999) 

請注意,您的測試現在會失敗。我不確定這是你想測試的。

+0

但問題是'foo(999)'不會引發BadStartException異常,它是'AttributeError'! – jonrsharpe

+0

@jonrsharpe這是'foo'的問題,而不是這個答案的問題。不要舉'例外'! – o11c