2014-12-22 21 views
3

我想用某些類級變量在一個類上運行幾個unittests。由於單元測試代碼保持對類的引用,所以類級變量不會重置爲預運行值。除了在被測試的類的初始化方法中重置所有類級變量之外,如何爲每個單元測試方法獲得新類?刪除單元測試之間對Python類的引用

class NonEmptyClassTest(unittest.TestCase): 

    def test_makeName(self): 
     nec = NonEmptyClass() 
     nec.addName("Fred") 
     nec.printAllData() 
     self.assertEquals(1 , len(nec.dummy_data)) 

    def test_makeName_1(self): 
     nec = NonEmptyClass() 
     nec.addName("Fred") 
     nec.printAllData() 
     self.assertEquals(1 , len(nec.dummy_data)) 


class NonEmptyClass(object): 
    dummy_data = {} 

    def printAllData(self): 
     for k,v in self.dummy_data.items(): 
      print k, v 

    def addName(self, name): 
     if not name in self.dummy_data: 
      self.dummy_data[name] = name+"_value" 
     else: 
      name = name + ".1" 
      self.dummy_data[name] = name+"_value" 

回答

2

這是模塊該類定義,保留一個引用。並且模塊本身保存在sys.modules中,以防止每次通過import語句在另一個模塊中使用模塊頂級代碼時重複運行模塊頂級代碼。

確保您的單元測試是在單獨的模塊中定義的,並將類的導入移動到幫助函數中,在此確保模塊在導入前先被刪除。這保證了模塊重新創建每次:

import sys 

class NonEmptyClassTest(unittest.TestCase): 
    def _makeOne(self, clear=False): 
     if clear: 
      try: 
       del sys.modules['module_name'] 
      except KeyError: 
       pass 
     from module_name import NonEmptyClass 
     return NonEmptyClass 

    def test_makeName(self): 
     nec = self._makeOne(clear=True) 
     nec.addName("Fred") 
     nec.printAllData() 
     self.assertEquals(1 , len(nec.dummy_data)) 

    def test_makeName_1(self): 
     nec = self._makeOne(clear=True) 
     nec.addName("Fred") 
     nec.printAllData() 
     self.assertEquals(1 , len(nec.dummy_data)) 

clear關鍵字參數,可以在不清除模塊營造一個以上的實例,以測試該數據確實正在實例之間共享。

-1

,如果你想你的類對類定義的值instantiaton添加__init__方法的類:

class NonEmptyClass(object): 

    def __init__(self): 
     self.dummy_data = {} 

    def printAllData(self): 
     for k,v in self.dummy_data.items(): 
      print k, v 

    def addName(self, name): 
     if not name in self.dummy_data: 
      self.dummy_data[name] = name+"_value" 
     else: 
      name = name + ".1" 
      self.dummy_data[name] = name+"_value" 

編輯

如果只有測試基於使用準備從類對象中重新定義變量:

class NonEmptyClassTest(unittest.TestCase): 

    nec = None 

    def setUp(self): 
     NonEmptyClass.dummy_data = {} 
     self.nec = NonEmptyClass() 

    def test_makeName(self): 
     self.nec.addName("Fred") 
     self.nec.printAllData() 
     self.assertEquals(1 , len(self.nec.dummy_data)) 

    def test_makeName_1(self): 
     self.nec.addName("Fred") 
     self.nec.printAllData() 
     self.assertEquals(1 , len(self.nec.dummy_data)) 
+0

這個相當擊敗類級變量的整點。 OP **希望班級共享字典。只是不在單元測試。 –

4

您可以使用setUp()來清除字典並使所有測試用例獨立。這是單元測試,這是一個好主意,他們不依賴於彼此和運行順序。

class NonEmptyClassTest(unittest.TestCase): 
    def setUp(self): 
     NonEmptyClass.dummy_data = {} 

    def test_makeName(self): 
     nec = NonEmptyClass() 
     nec.addName("Fred") 
     nec.printAllData() 
     self.assertEquals(1 , len(nec.dummy_data)) 

    def test_makeName_1(self): 
     nec = NonEmptyClass() 
     nec.addName("Fred") 
     nec.printAllData() 
     self.assertEquals(1 , len(nec.dummy_data)) 

[編輯]

從評論。恕我直言,明確寫出什麼是類變量,以及如何重置它使測試更清晰,並給你一些更有用的檢查點。

當然,如果你添加更多的類變量,你必須更新你的setUp()測試用例,但我認爲這是一個加號。測試必須清楚,不應該隱藏像這樣的行爲。

+2

如果他有很多初始化的類變量會怎麼樣 –

+0

他說的是帶有一些類變量的_a類,所以他必須清理所有的類變量。它是否以明確的方式使測試變得清晰和簡單:此外還要記住測試中什麼是類變量。 –

1

您應該避免在類變量上使用可變對象。請參閱本教程:https://docs.python.org/2/tutorial/classes.html#class-and-instance-variables

如前所述通過@markcial在他原始的未經編輯的答案,你必須得讓你dummy_data實例變量代替類變量

試圖調整你的測試通過,而不是做一些setUp方法hack和變量重新初始化是一個跡象,表明你實際測試的類的底層實現有一個實現缺陷。

所以,你寧可修復類,而不是與其單元測試摔跤。因此,我複製和粘貼 @這裏markcial原來的答案,只修復類的實現:

class NonEmptyClass(object): 

    def __init__(self): 
     self.dummy_data = {} 

    def printAllData(self): 
     for k, v in self.dummy_data.items(): 
      print k, v 

    def addName(self, name): 
     if name not in self.dummy_data: 
      self.dummy_data[name] = name + "_value" 
     else: 
      self.dummy_data[name] = name + ".1_value" 
+1

有兩種使用可變類正當理由的屬性 - 「不使用類屬性」就像_any_「黃金法則」:不這樣做 - 除非你_really_明白爲什麼它可能是一個壞主意;) –

+0

由* *應該避免**我打算表示**應該抵制...... **。就像使用可變變量作爲函數的默認參數一樣。它比有用的更有害。即使在這種情況下,使用可變類變量並不意味着某種特殊原因,而只是一種疏忽。 – dopstar

+0

我們顯然同意這樣一個事實,即可變類的屬性常常是一個壞主意 - 但這並不意味着有沒有合理的理由來使用它們。 –