| 導航:起始頁 > Dive Into Python > 單元測試 > 負面測試 (Testing for failure) | << >> | ||||
深入 Python :Dive Into Python 中文版Python 從新手到專家 [Dip_5.4b_CPyUG_Release] |
|||||
使用有效輸入確保函數成功通過測試還不夠,你還需要測試無效輸入導致函數失敗的情形。但并不是任何失敗都可以,必須如你預期地失敗。
還記得 toRoman 的其他要求吧:
在 Python 中,函數以引發異常的方式表示失敗。unittest 模塊提供了用于測試函數是否在給定無效輸入時引發特定異常的方法。
class ToRomanBadInput(unittest.TestCase): def testTooLarge(self): """toRoman should fail with large input""" self.assertRaises(roman.OutOfRangeError, roman.toRoman, 4000)def testZero(self): """toRoman should fail with 0 input""" self.assertRaises(roman.OutOfRangeError, roman.toRoman, 0)
def testNegative(self): """toRoman should fail with negative input""" self.assertRaises(roman.OutOfRangeError, roman.toRoman, -1) def testNonInteger(self): """toRoman should fail with non-integer input""" self.assertRaises(roman.NotIntegerError, roman.toRoman, 0.5)
| unittest 模塊中的 TestCase 類提供了 assertRaises 方法,它接受這幾個參數:預期的異常、測試的函數,以及傳遞給函數的參數。(如果被測試函數有不止一個參數,把它們按順序全部傳遞給 assertRaises ,它會把這些參數傳給被測的函數。) 特別注意這里的操作:不是直接調用 toRoman 再手工查看是否引發特定異常 (使用 try...except 塊捕捉異常),assertRaises 為我們封裝了這些。所有你要做的就是把異常 (roman.OutOfRangeError)、函數 (toRoman) 以及 toRoman 的參數 (4000) 傳遞給 assertRaises ,它會調用 toRoman 查看是否引發 roman.OutOfRangeError 異常。(還應注意到你是把 toRoman 函數本身當作一個參數,而不是調用它,傳遞它的時候也不是把它的名字作為一個字符串。我提到過嗎?無論是函數還是異常, Python 中萬物皆對象)。 | |
| 與測試過大的數相伴的便是測試過小的數。記住,羅馬數字不能表示 0 和負數,所以你要分別編寫測試用例 ( testZero 和 testNegative)。在 testZero 中,你測試 toRoman 調用 0 引發的 roman.OutOfRangeError 異常,如果沒能 引發 roman.OutOfRangeError (不論是返回了一個值還是引發了其他異常),則測試失敗。 | |
| 要求 #3:toRoman 不能接受非整數輸入,所以這里你測試 toRoman 在輸入 0.5 時引發 roman.NotIntegerError 異常。如果 toRoman 沒有引發 roman.NotIntegerError 異常,則測試失敗。 |
接下來的兩個要求與前三個類似,不同點是他們所針對的是 fromRoman 而不是 toRoman:
要求 #4 與要求 #1 的處理方法相同,即測試一個已知樣本中的一個個數字對。要求 #5 與 #2 和 #3的處理方法相同,即通過無效輸入確認 fromRoman 引發恰當的異常。
class FromRomanBadInput(unittest.TestCase): def testTooManyRepeatedNumerals(self): """fromRoman should fail with too many repeated numerals""" for s in ('MMMM', 'DD', 'CCCC', 'LL', 'XXXX', 'VV', 'IIII'): self.assertRaises(roman.InvalidRomanNumeralError, roman.fromRoman, s)def testRepeatedPairs(self): """fromRoman should fail with repeated pairs of numerals""" for s in ('CMCM', 'CDCD', 'XCXC', 'XLXL', 'IXIX', 'IVIV'): self.assertRaises(roman.InvalidRomanNumeralError, roman.fromRoman, s) def testMalformedAntecedent(self): """fromRoman should fail with malformed antecedents""" for s in ('IIMXCC', 'VX', 'DCM', 'CMM', 'IXIV', 'MCMC', 'XCX', 'IVI', 'LM', 'LD', 'LC'): self.assertRaises(roman.InvalidRomanNumeralError, roman.fromRoman, s)
<< 正面測試 (Testing for success) |
| 1 | 2 | 3 | 4 | 5 | 6 | |
完備性檢測 (Testing for sanity) >> |