2011-05-23 36 views
120

我做了一個簡單的測試案例:如何在NoneType對象中正確使用單元測試的assertRaises()?

def setUp(self): 

    self.testListNone = None 

def testListSlicing(self): 

    self.assertRaises(TypeError, self.testListNone[:1]) 

,我期待着測試通過,但我得到異常:

Traceback (most recent call last): 

    self.assertRaises(TypeError, self.testListNone[:1]) 

TypeError: 'NoneType' object is unsubscriptable 

我認爲assertRaises會通過,因爲TypeError異常會 是上調?

回答

182

如果您正在使用python2.7以上可以使用的assertRaises的能力是用作上下文管理器,並做到:

with self.assertRaises(TypeError): 
    self.testListNone[:1] 

如果您正在使用python2.6的另一種方式給身邊到現在爲止的一個方法是使用unittest2這是單元測試新功能python2.6的的背面端口,你可以把它的工作使用上面的代碼。

N.B:我是新功能的大風扇(SkipTest,測試發現...)的單元測試,所以我打算用unittest2爲盡我所能。我建議做同樣的事情,因爲python2.6 <中有很多單元測試。

63

使用assertRaises的通常的方法是調用一個函數:

self.assertRaises(TypeError, test_function, args) 

測試,該函數調用test_function(參數)提出一個TypeError。

self.testListNone[:1]的問題是Python在調用assertRaises方法之前立即計算表達式。爲什麼test_functionargs作爲單獨參數傳遞到self.assertRaises的全部原因是允許assertRaisestry...except塊中調用test_function(args),允許assertRaises捕獲該異常。

既然你已經定義self.testListNone = None,你需要一個函數來調用,您可以使用operator.itemgetter這樣的:

import operator 
self.assertRaises(TypeError, operator.itemgetter, (self.testListNone,slice(None,1))) 

因爲

operator.itemgetter(self.testListNone,slice(None,1)) 

是說self.testListNone[:1]的長篇大論方式,但它將函數(operator.itemgetter)與參數分開。

+2

對於單個assertRaises,這看起來像是最好的答案。對於大量基於異常的測試(假設它們都具有相同的異常類型),使用self.assertRaises(...)將是一個不錯的選擇。 – user632657 2014-05-01 17:55:56

+1

是的,這應該是正確的答案,因爲它實際上解釋了問題。 – 2014-10-03 14:59:12

+1

這絕對是正確的答案,它解釋了這個問題。 – Ismael 2014-12-11 13:31:22

100

問題是TypeError在'assertRaises被調用之前得到提升,因爲在調用該方法之前需要先評估assertRaises的參數。你需要通過一個lambda表達,如:

self.assertRaises(TypeError, lambda: self.testListNone[:1]) 
+1

可能最好的答案 – 2016-07-12 13:18:33

+0

你能請幫助我解決相關問題? https://stackoverflow.com/questions/39909935/how-do-you-show-an-error-message-when-a-test-does-not-throw-an-expected-exceptio – 2016-10-07 17:11:27

2

完整的片段看起來像下面這樣。它擴展了@ mouad對錯誤消息(或其args的一般str表示)進行斷言的回答,這可能是有用的。

from unittest import TestCase 


class TestNoneTypeError(TestCase): 

    def setUp(self): 
    self.testListNone = None 

    def testListSlicing(self): 
    with self.assertRaises(TypeError) as ctx: 
     self.testListNone[:1] 
    self.assertEqual("'NoneType' object is not subscriptable", str(ctx.exception)) 
相關問題