簡體   English   中英

如何避免從元類派生的動態生成的類不以相同的類結尾?

[英]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詞典查找testtestOnetestOne時間test設置為它最近設置的值。

您需要強制綁定更早發生,這可以通過簡單地更改來實現

        def testOne(self):

        def testOne(self, test=test):

此更改將強制在def執行時(而不是在稍后執行方法主體時)查找全局test ,這與class語句執行的時間相同-即,循環的每個分支都執行一次,當全局變量test設置為列表tests的當前項目時。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM