簡體   English   中英

對Python構造函數中的異常進行單元測試

[英]Unit testing for exceptions in Python constructor

我只是一般的Python和編程初學者,並且對unittest模塊有一些疑問。

我有一個類,在__init__方法中,我正在做一些斷言來檢查錯誤的參數。 我想創建一個在創建新實例時檢查此類AssertionError的單元測試。

在unittest模塊中,可以在調用callable時測試(使用assertRaises )是否有特定的異常,但是顯然這將適用於該類的方法。 對構造函數運行這種測試的正確方法是什么?

我知道我可以嘗試創建帶有錯誤參數的類的實例,並且unittest將報告測試失敗,但是在第一個此類異常發生后立即停止,即使我可以將多個測試包裝在多個測試函數中,它看起來一點也不優雅。

在unittest模塊中,可以在調用callable時測試(使用assertRaises )是否有特定的異常,但是顯然這將適用於該類的方法。 對構造函數運行這種測試的正確方法是什么?

構造函數本身是可調用的:

self.assertRaises(AssertionError, MyClass, arg1, arg2)

話雖如此,我想回應nosklo和S.Lott對參數進行類型檢查的擔憂。 此外,您不應該使用斷言來檢查函數參數:斷言是最有用的方法,因為除非代碼內部出現問題,否則不會觸發健全性檢查。 同樣,當Python以“優化” -O模式運行時,assert語句也會被編譯出來。 如果函數需要對其參數進行某種形式的檢查,則應引發適當的異常。

不要搞混assertRaises。 它太復雜了。

做這個

class Test_Init( unittest.TestCase ):
    def test_something( self ):
        try:
            x= Something( "This Should Fail" )
            self.fail( "Didn't raise AssertionError" )
        except AssertionError, e:
            self.assertEquals( "Expected Message", e.message )
            self.assertEquals( args, e.args )

任何其他異常將是普通的測試錯誤。

另外,不要在__init__方法中進行過多的前期錯誤檢查。 如果有人提供了錯誤類型的對象,則您的代碼將在正常事件過程中失敗,並通過正常方式引發正常異常。 您無需過多地“預篩選”對象。

不知道這有幫助,但是我遇到的一個問題如下:

self.assertRaises(Exception, MyFunction())

問題是我不僅傳遞了MyFunction ,還調用了它,導致失敗並引發Exception。 Myfunction期望有一個參數,如果沒有傳入任何參數,我希望它失敗。讓我沮喪了一段時間,直到我弄清楚了:

self.assertRaises(Exception, MyFunction)

可以正常工作。

好吧,首先,在python中檢查錯誤的參數不是一個好主意。 Python是動態強類型的,這是有原因的。

您應該僅假設參數是好的參數。 您永遠不會知道類的用戶意圖,因此通過檢查良好的參數是一種在更通用的實例中限制類使用的方法。

而是定義一個好的API並使用docstring和文本很好地記錄下來,並將錯誤參數的錯誤自動流向用戶。

例:

def sum_two_values(value_a, value_b):
    return value_a + value_b

好的,這個例子很愚蠢,但是如果我檢查並斷言該值是整數,那么除了我的檢查外,該函數將不能用於浮點數,字符串,列表,那么為什么要首先檢查呢? 它會因無法使用的類型而自動失敗,因此您不必擔心。

self.fail()的答案是不正確的: self.fail()本身會引發異常,然后由以下行中的異常引起:

class NetworkConfigTest1(unittest.TestCase):
    def runTest(self):
        try:
            NetworkConfig("192.168.256.0/24")
            self.fail("Exception expected but not thrown")
        except Exception, error:
            printf("Exception caught: %s" % str(error)
            pass

輸出為“預期但未引發異常”,但是即使未編寫要測試的代碼,單元測試也未標記為失敗!

檢查方法是否引發異常的更有效方法是使用:

self.failUnlessRaises([error], [callable], [arguments to callable])

就我而言,我正在測試的類稱為NetworkConfig ,並且如果網絡描述符無效,則構造函數必須引發異常。 起作用的是:

class NetworkConfigTest1(unittest.TestCase):
    def runTest(self):
        self.failUnlessRaises(Exception, NetworkConfig, "192.168.256.0/24")

這可以按需工作並執行正確的測試。

如果只想檢查構造函數是否引發異常,那么使用lambda更好:

    def testInsufficientArgs(self):
        self.assertRaises(ValueError, lambda: MyClass(0))

這樣,構造器參數就不會“神奇地”設置(就像在@Miles的答案中一樣),並且IDE總是可以告訴您構造器的使用位置。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM