2010-01-14 118 views
10

考慮:Python的 - 測試屬性拋出異常

def test_to_check_exception_is_thrown(self): 
    # Arrange 
    c = Class() 
    # Act and Assert 
    self.assertRaises(NameError, c.do_something) 

如果do_something拋出測試通過一個例外。

但是我有一個屬性,當我用c.do_something替換c.name = "Name"時,我得到一個關於我的測試模塊未被導入的錯誤,並且Eclipse突出顯示了等號。

我如何測試一個屬性拋出異常?

編輯:

setattrgetattr是新的我。在這種情況下,他們肯定有幫助,謝謝。

回答

13

assertRaises預計一可調用對象。你可以創建一個函數,並將它傳遞:

obj = Class() 
def setNameTest(): 
    obj.name = "Name"   
self.assertRaises(NameError, setNameTest) 

另一種可能性是使用setattr

self.assertRaises(NameError, setattr, obj, "name", "Name") 

你原來代碼中引發了一個語法錯誤,因爲賦值是一個語句,不能放置在表達式中。

+2

由於python 2.7+應該簽出@RaphaelAhrens以下答案。這是更多pythonic http:// stackoverflow。com/a/23650764/601245 – 2016-09-09 14:55:24

-1

你會得到一個錯誤,因爲它是Python中的一個語法錯誤,在另一個表達式中有一個賦值。例如:

>>> print(foo = 'bar') 
------------------------------------------------------------ 
    File "<ipython console>", line 1 
    print(foo = 'bar') 
      ^
SyntaxError: invalid syntax 

但在兩個步驟做它工作正常:

>>> foo = 'bar' 
>>> print(foo) 
bar 

要測試的屬性拋出一個異常,使用try塊:

try: 
    object.property = 'error' 
except ExpectedError: 
    test_passes() 
else: 
    test_fails() 
+0

這是矯枉過正並沒有真正適合使用單元測試。 – 2010-01-14 17:47:54

8

The second argument to assertRaises should be a callable

賦值語句(即class.name = "Name")不是可調用的,因此它不起作用。使用setattr像這樣

self.assertRaises(NameError, setattr, myclass, "name", "Name") 

進行分配此外,因爲它是一個關鍵詞,你不能分配給class

+0

這是僞代碼,用來鏡像我的代碼。但我知道 ;) – Finglas 2010-01-14 17:48:12

10

由於Python 2.7和3.1 assertRaises()可以用作上下文管理器。見here for Python 2here for Python3

所以,你可以用這樣的with指令編寫測試:

def test_to_check_exception_is_thrown(self): 
    c = Class() 
    with self.assertRaises(NameError): 
     c.name = "Name" 
0

由於@interjay表示,它期待一個callble,但歐並不真正需要定義一個名爲功能對於這一點,拉姆達將做到這一點:

self.assertRaises(SomeException, lambda: my_instance.some_property)