2011-07-11 35 views
29

我正在爲我的應用程序使用Python的unittest編寫一些測試用例。現在我需要將對象列表與另一個對象列表進行比較,以檢查第一個列表中的對象是否是我期望的內容。如何在Python中編寫自定義的`.assertFoo()`方法?

我該如何編寫自定義的.assertFoo()方法?它應該做什麼?它應該在失敗時引發異常嗎?如果是,哪個例外?以及如何傳遞錯誤消息?錯誤消息應該是unicode字符串還是字符串?

不幸的是,official documentation沒有解釋如何編寫自定義斷言方法。

如果您需要一個真實世界的例子,請繼續閱讀。


我寫的代碼是有點像這樣:

def assert_object_list(self, objs, expected): 
    for index, (item, values) in enumerate(zip(objs, expected)): 
     self.assertEqual(
      item.foo, values[0], 
      'Item {0}: {1} != {2}'.format(index, item.foo, values[0]) 
     ) 
     self.assertEqual(
      item.bar, values[1], 
      'Item {0}: {1} != {2}'.format(index, item.bar, values[1]) 
     ) 

def test_foobar(self): 
    objs = [...] # Some processing here 
    expected = [ 
     # Expected values for ".foo" and ".bar" for each object 
     (1, 'something'), 
     (2, 'nothing'), 
    ] 
    self.assert_object_list(objs, expected) 

這種方法使得它非常容易來形容一個非常緊湊的方式,每個對象的預期值,而無需實際創建完整的對象。

但是...當一個對象失敗斷言時,沒有進一步的對象進行比較,這使調試更加困難。我想編寫一個自定義的方法,無條件地比較所有的對象,然後顯示所有失敗的對象,而不是第一個。

回答

27

我在這些情況下使用多重繼承。例如:

首先。我定義了一個包含方法的類。

import os 

class CustomAssertions: 
    def assertFileExists(self, path): 
     if not os.path.lexists(path): 
      raise AssertionError('File not exists in path "' + path + '".') 

現在我定義了從和unittest.TestCase生成CustomAssertion

import unittest 

class MyTest(unittest.TestCase, CustomAssertions): 
    def test_file_exists(self): 
     self.assertFileExists('any/file/path') 

if __name__ == '__main__': 
    unittest.main() 
+3

很好的替代方法 - 這是有幫助的。 –

+7

這種方法也被稱爲[mixin](https://en.wikipedia.org/wiki/Mixin#In_Python)。 –

+0

@DenilsonSáMaia - 可以讓自定義斷言返回一些東西嗎? –

17

你應該創建你自己的TestCase類,派生自unittest.TestCase。然後將自定義斷言方法放入該測試用例類中。如果你的測試失敗,引發一個AssertionError。你的消息應該是一個字符串。如果要測試列表中的所有對象而不是停止發生故障,請收集失敗索引的列表,並在循環遍歷所有對象之後,構建一條總結您的發現的斷言消息。

+1

有什麼區別在提高一個'AssertionError'和其他'Exception'(關於自定義斷言和'unittest')? – hiwaylon

0

只是一個例子繼承的類與numpy的comparaison總結單元測試

import numpy as np 
class CustomTestCase(unittest.TestCase): 
    def npAssertAlmostEqual(self, first, second, rtol=1e-06, atol=1e-08): 
     np.testing.assert_allclose(first, second, rtol=rtol, atol=atol) 


class TestVector(CustomTestCase): 
    def testFunction(self): 
     vx = np.random.rand(size) 
     vy = np.random.rand(size) 
     self.npAssertAlmostEqual(vx, vy) 
相關問題