至於爲何要動態生成unittest執行腳本,以及設計思路,代碼閱讀參考前文,傳送門。好了,本文咱們就上一篇文章中的問題作一下分析,記錄一下填坑之路吧,這個坑真特麼深,掙扎了很久纔出來。html
首先咱們先說一下問題在哪,由於使用了閉包,閉包會綁定變量沒法清除沒法更改,假如我第一次運行testall函數循環兩次,第一次是正常的,第二次運行testall函數循環一次,那麼生成的報告就會出現問題,會出現第一次運行的結果。便是:後一次循環運行只要比前一次循環少,那麼report必定會出現前一次的結果,必先的bug。python
好了,咱們聊一下前文動態生成unittest執行腳本的坑有多深吧,主要涉及閉包,又由於閉包循環調用unittest的Test類添加方法組成suite,你們都知道Python的閉包會綁定變量,沒法清除沒法改變,咱們把相關代碼貼出來吧,方便看。api
1 class Test(unittest.TestCase): # TestCase類 2 "測試類" 3 4 def begin_req(self, apidata): # 類方法 5 back = run_single_testcase(apidata) # 調用請求 6 YQ = 200 # 結果對比 7 SJ = back.status_code 8 self.assertEqual(SJ, YQ) 9 10 def demo(apidata): # 閉包 11 def tool(self): 12 Test.begin_req(self, apidata) # 調用Test方法 13 14 setattr(tool, '__doc__', u'測試%s' % str(apidata['name'])) 15 return tool 16 17 def testall(apidata): # 循環調用閉包 18 for i in range(len(apidata)): 19 setattr(Test, 'test_' + str(i + 1), demo(apidata[i])) 20 21 def suite(Apidata): # 調用testall拼裝Test類,組裝suit 22 testall(Apidata) 23 suit = unittest.makeSuite(Test) 24 return suit
代碼釋義: 類Test繼承unittest.TestCase沒啥好說的,方法demo閉包內部函數tool,tool方法的第一個參數self是Test類(我理解爲指針指向Test類),函數testall循環調用閉包,函數suite我上面註釋寫的很清楚了閉包
這個坑有很大的迷惑性,我有很大一部分時間都在關注閉包函數,我認爲是閉包致使的,一直在研究閉包哪裏出錯了,還有要如何更改閉包函數的參數,用了不少方法,什麼容器裝參數,後面刪除容器成員啥的,全用上了...MMP...結果確實是閉包致使的,可是問題沒有出在閉包函數處,要理解閉包請參考其餘文章,傳送門,咱們就不白話了,上解決的代碼吧app
1 def testall(apidata): 2 nameList = [] 3 for i in range(len(apidata)): 4 name = 'test_' + str(i + 1) 5 setattr(Test, name, demo(apidata[i])) 6 nameList.append(name) 7 return nameList 8 9 def suite(Apidata): 10 nameList = testall(Apidata) 11 suites = unittest.TestSuite() 12 for i in nameList: 13 suites.addTest(Test(i)) 14 return suites
主要修改了testall函數和suite函數,其實問題出在suite函數裏,原有函數以下代碼函數
1 def suite(Apidata): # 調用testall拼裝Test類,組裝suit 2 testall(Apidata) 3 suit = unittest.makeSuite(Test) 4 return suit
第三行中makeSuite函數,是指一次性添加Test類的方法到suite,結果閉包綁定的對象(python一切皆對象)在Test裏,第一次運行組裝的Test類方法被閉包綁定,後一次運行若是比前一次少,那麼就會有沒有被覆蓋的方法,就會出現錯誤,因此修改makeSuite函數爲addTest函數,問題就解決了,我研究了好久的閉包啊,結果問題出在了Test類上,真心心累。文筆太差..見諒..多謝..測試