[英]How can I avoid dynamically generated classes derived from metaclass not to end up as the same class?
我想做的是對一個函數執行數百個單元測試,我可以從一個字典中得出。 不幸的是,我無法使用任何現有的軟件包進行參數化測試(例如鼻子),因此我試圖獲得自己的解決方案。
我的以下示例代碼意圖是創建3個類(每個測試一個),這些類將存在於全局范圍內,以便單元測試可以選擇它並運行相應的測試。
tests = [
{'text': 'text1fdskla3fsda4',
'result': [1, 3, 4],
},
{'text': 'fdsg45tg5b',
'result': [4, 5, 5,5 ],
},
{'text': 'fsddf4',
'result': [4, 2],
}
]
def evaluate(text):
out = []
for char in text:
if char.isdigit():
out.append(int(char))
return out
class TestMeta(type):
def __new__(cls, name, bases, attrs):
name = str(test['text'])
return type.__new__(cls, name, (unittest.TestCase,), attrs)
for test in tests:
class T(object):
__metaclass__ = TestMeta
def testOne(self):
self.assertEqual(test['result'], evaluate(test['text']))
globals()[(test['text'])] = copy.deepcopy(T)
unittest.main()
當我運行上面的代碼時,我得到了四個單元測試,比預期的多一個,但是最重要的是,我沒有創建每個單元測試的輸出,而是好像我正在創建的類始終是相同的(即使我實際上為每個設置了不同的名稱和參數):
======================================================================
FAIL: testOne (__main__.fsddf4)
----------------------------------------------------------------------
Traceback (most recent call last):
File "ble.py", line 45, in testOne
self.assertEqual(test['result'], evaluate(test['text']))
AssertionError: [4, 2] != [4]
======================================================================
FAIL: testOne (__main__.fdsg45tg5b)
----------------------------------------------------------------------
Traceback (most recent call last):
File "ble.py", line 45, in testOne
self.assertEqual(test['result'], evaluate(test['text']))
AssertionError: [4, 2] != [4]
======================================================================
FAIL: testOne (__main__.fsddf4)
----------------------------------------------------------------------
Traceback (most recent call last):
File "ble.py", line 45, in testOne
self.assertEqual(test['result'], evaluate(test['text']))
AssertionError: [4, 2] != [4]
======================================================================
FAIL: testOne (__main__.text1fdskla3fsda4)
----------------------------------------------------------------------
Traceback (most recent call last):
File "ble.py", line 45, in testOne
self.assertEqual(test['result'], evaluate(test['text']))
AssertionError: [4, 2] != [4]
----------------------------------------------------------------------
Ran 4 tests in 0.002s
FAILED (failures=4)
deepcopy是嘗試獲得不同的輸出,但沒有幫助。 在globals字典中顯式創建該類是由於以下事實:僅在for循環上創建類僅會產生一個unittest。
除了對元一切的深入嘗試之外,您還遇到了一個典型的Python初學者問題:全局名稱查找是在運行時完成的。
因此,在您的代碼中:
for test in tests:
class T(object):
__metaclass__ = TestMeta
def testOne(self):
self.assertEqual(test['result'], evaluate(test['text']))
當testOne
運行時,它會在那時 (即運行的時間)在globals
詞典中查找test
, testOne
, testOne
時間test
設置為它最近設置的值。
您需要強制綁定更早發生,這可以通過簡單地更改來實現
def testOne(self):
成
def testOne(self, test=test):
此更改將強制在def
執行時(而不是在稍后執行方法主體時)查找全局test
,這與class
語句執行的時間相同-即,循環的每個分支都執行一次,當全局變量test
設置為列表tests
的當前項目時。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.