2013-09-30 24 views
7

我試圖通過對unittest.testcase類進行子分類來創建自定義單元測試框架,但在處理__init__方法時似乎犯了一個錯誤。在python中重載unittest.testcase

我不明白爲什麼ComplexTest的構造函數沒有在BasicTest之前調用,而且這個異常也似乎與我的構造函數有關。

我對Python很新,所以對於如何解決這個特定問題或其他架構對我的用例的任何幫助將是最受歡迎的。

謝謝!

1)test_framework.py

import unittest 

class BasicTest(unittest.TestCase): 
    def __init__(self, *args, **kwargs): 
     print('BasicTest.__init__') 
     super(unittest.TestCase, self).__init__(*args, **kwargs) 

    def setUp(self): 
     print('BasicTest.setUp') 
     super(unittest.TestCase, self).tearDown() 

    def tearDown(self): 
     print('BasicTest.tearDown') 
     super(unittest.TestCase, self).tearDown() 


class ComplexTest(BasicTest): 
    def __init__(self, *args, **kwargs): 
     print('ComplexTest.__init__') 
     super(BasicTest, self).__init__(*args, **kwargs) 

    def setUp(self): 
     print('ComplexTest.setUp') 
     super(BasicTest, self).tearDown() 

    def tearDown(self): 
     print('ComplexTest.tearDown') 
     super(BasicTest, self).tearDown() 

2)test.py

import unittest 
import test_framework 

class TestValueFunctions(test_framework.ComplexTest): 
    def __init__(self, *args, **kwargs): 
     print('TestValueFunctions.__init__') 
     super(test_framework.ComplexTest, self).__init__(*args, **kwargs) 

    def setUp(self): 
     print('TestValueFunctions.setUp') 
     super(test_framework.ComplexTest, self).tearDown() 
     self.value = 4711 

    def tearDown(self): 
     print('TestValueFunctions.tearDown') 
     super(test_framework.ComplexTest, self).tearDown() 

    def test_value(self): 
     print('TestValueFunctions.test_value') 
     self.assertEqual(self.value, 4711) 

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

3)當現在試圖運行此,我看到以下堆棧

TestValueFunctions.__init__ 
BasicTest.__init__ 
Traceback (most recent call last): 
    File "D:\MyDev\ljs_app\trunk\examples\python\unittest\test.py", line 23, in <module> 
    unittest.main() 
    File "C:\Python27\lib\unittest\main.py", line 94, in __init__ 
    self.parseArgs(argv) 
    File "C:\Python27\lib\unittest\main.py", line 149, in parseArgs 
    self.createTests() 
    File "C:\Python27\lib\unittest\main.py", line 155, in createTests 
    self.test = self.testLoader.loadTestsFromModule(self.module) 
    File "C:\Python27\lib\unittest\loader.py", line 65, in loadTestsFromModule 
    tests.append(self.loadTestsFromTestCase(obj)) 
    File "C:\Python27\lib\unittest\loader.py", line 56, in loadTestsFromTestCase 
    loaded_suite = self.suiteClass(map(testCaseClass, testCaseNames)) 
    File "D:\MyDev\ljs_app\trunk\examples\python\unittest\test.py", line 7, in __init__ 
    super(test_framework.ComplexTest, self).__init__(*args, **kwargs) 
    File "D:\MyDev\ljs_app\trunk\examples\python\unittest\test_framework.py", line 6, in __init__ 
    super(unittest.TestCase, self).__init__(*args, **kwargs) 
TypeError: object.__init__() takes no parameters 
+0

'super'的一大優點是你不必**必須顯式聲明超類。正如您在錯誤中看到的那樣,您正在使用該代碼調用'object .__ init__'而不是'TestCase .__ init__'。 – Bakuriu

+1

只有在Python 3中,你可以省略'super'的類參數。 – chepner

回答

17

事實上你的init方法是錯誤的。

class BasicTest(unittest.TestCase): 
    def __init__(self, *args, **kwargs): 
     print('BasicTest.__init__') 
     super(unittest.TestCase, self).__init__(*args, **kwargs) 

應該是:

class BasicTest(unittest.TestCase): 
    def __init__(self, *args, **kwargs): 
     print('BasicTest.__init__') 
     super(BasicTest, self).__init__(*args, **kwargs) 

這將調用__init__對母親類BasicTest,這是測試用例。這同樣適用於setUp和tearDown:

class BasicTest(unittest.TestCase): 
    ... 
    def setUp(self): 
     print('BasicTest.setUp') 
     super(BasicTest, self).setUp() 
+0

優秀:我似乎誤解了超級,但現在它像一個魅力。謝謝! – doberkofler

+0

setUp示例的最後一行應該是:'super(BasicTest,self).setUp()'。現在它將調用tearDown父方法,這不是邏輯。問題代碼樣本也一樣。 – manelvf

0

super!誰知道它爲什麼做任何事情。如果你停在你的測​​試使用它,而不是明確地調用父類的,你想,像這樣:

TestValueFunctions.__init__ 
ComplexTest.__init__ 
TestValueFunctions.setUp 
ComplexTest.setUp 
TestValueFunctions.test_value 
TestValueFunctions.tearDown 
ComplexTest.tearDown 
. 
---------------------------------------------------------------------- 
Ran 1 test in 0.000s 

OK 

參見:Python's Super is nifty, but you can't use it

class BasicTest(unittest.TestCase): 
    def __init__(self, *args, **kwargs): 
     print('BasicTest.__init__') 
     unittest.TestCase.__init__(self, *args, **kwargs) 

你會與下面的輸出結束

+0

只有當你不希望它是多重繼承的一部分時,這纔是真的;否則,這會破壞事情並可能導致意外的行爲。 –

+0

它不會破壞事物。特別是因爲'unittest.TestCase'不使用super。這是按照您想要調用的順序顯式調用您想要的代碼的情況。 – aychedee

+0

不是這樣的,如果你有這個類和另一個類,它們將'unittest.TestCase'子類作爲這個類的直接父類,或者另一種方法,使得它在mro中比另一個方法更早結束,那麼就會產生問題。在這種情況下可能更少,但更普遍的是它不是一個好選擇(特別是如果它是對象的直接子類) –