在前面的介紹中,我們對unittest進行了分享介紹,那麼在實際的應用中,因為客觀原因需要對失敗,錯誤的測試用例進行重試,所以呢,現有的unittest的框架無法滿足,那麼我們可以去改造下是否能夠滿足呢。本文帶領大家去剖析如何改寫?

首先呢,我們去試著去找下,我們執行時在BSTestRunner、TextTestRunner或者main,都可以執行用例,那麼我們可以看下這些類或者方法裡面如何實現的。

BSTestRunner呼叫方式如下

TextTestRunner的方法是,

使用main方法最後的呼叫也是這個函式。詳細的我們可以看下,首先呼叫這個函式,然後在看實際的呼叫.

最後的呼叫也是這個函式

所以我們就要在裡面的方法去查詢適合我們使用的方法。

在註釋中,我們可以發現在stopTest的方法中可以對其進行改寫。
def stopTest(self, test):
"""Called when the given test has been run"""
self._restoreStdout()
self._mirrorOutput = False

  

那麼我們應該如何改寫呢,我們梳理下我們的思路。

  • 1.傳遞重試次數,預設不需要重試
  • 2.在用例執行的錯誤,標記為需要重試
  • 3.在該條用例執行完畢後,我們判斷是否需要重試,重試次數是否滿足
  • 4.如果需要重試,則儲存最新的從測試結果。

那麼我們開始按照上面的思路進行改造。

程式碼如下

import  sys,copy
from io import StringIO as StringIO
TestResult = unittest.TestResult
class MyResult(TestResult):
def __init__(self, verbosity=1, trynum=0):
#預設次數是0
TestResult.__init__(self)
self.outputBuffer = StringIO()
self.stdout0 = None
self.stderr0 = None
self.success_count = 0
self.failure_count = 0
self.error_count = 0
self.verbosity = verbosity
self.trynnum = trynum
self.result = []
self.trys=0#
self.istry=False def startTest(self, test):
TestResult.startTest(self, test)
self.stdout0 = sys.stdout
self.stderr0 = sys.stderr def complete_output(self):
if self.stdout0:
sys.stdout = self.stdout0
sys.stderr = self.stderr0
self.stdout0 = None
self.stderr0 = None
return self.outputBuffer.getvalue() def stopTest(self, test):
#判斷是否要重試
if self.istry is True :
#如果執行的次數小於重試的次數 就重試
if self.trys < self.trynnum :
#刪除最後一個結果
reslut = self.result.pop(-1)
#判斷結果,如果是錯誤就把錯誤的個數減掉
#如果是失敗,就把失敗的次數減掉
if reslut[0] == 1:
self.failure_count -= 1
else:
self.error_count -= 1
sys.stderr.write('{}:用例正在重試中。。。' .format(test.id())+ '\n')
#深copy用例
test = copy.copy(test)
#重試次數增加+1
self.trys += 1
#測試
test(self)
else:
self.istry=False
self.trys =0
self.complete_output() def addSuccess(self, test):
#成功就不要重試
self.istry = False
self.success_count += 1
TestResult.addSuccess(self, test)
output = self.complete_output()
self.result.append((0, test, output, ''))
if self.verbosity > 1:
sys.stderr.write('ok ')
sys.stderr.write(str(test))
sys.stderr.write('\n')
else:
sys.stderr.write('.') def addError(self, test, err):
#重試+1,錯誤次數+1
self.istry = True
self.error_count += 1
TestResult.addError(self, test, err)
_, _exc_str = self.errors[-1]
output = self.complete_output()
self.result.append((2, test, output, _exc_str))
if self.verbosity > 1:
sys.stderr.write('E ')
sys.stderr.write(str(test))
sys.stderr.write('\n')
else:
sys.stderr.write('E') def addFailure(self, test, err):
self.istry = True
TestResult.startTestRun(self)
self.failure_count += 1
TestResult.addFailure(self, test, err)
_, _exc_str = self.failures[-1]
output = self.complete_output()
self.result.append((1, test, output, _exc_str))
if self.verbosity > 1:
sys.stderr.write('F ')
sys.stderr.write(str(test))
sys.stderr.write('\n')
else:
sys.stderr.write('F') def stop(self) -> None:
pass

這樣改造完畢了,我們可以去試試

if __name__ == "__main__":
suitone=suite()   
rse=MyResult(trynum=3)
suitone.run(rse)

執行的結果如下:

目前改造滿足我們重試用例的需求,改造完畢。

上面只是一個簡單的改造,滿足了對於失敗的測試用例的重試,其實很簡單,我們有了需求,去根據我們的需求去查詢需要改造的程式碼即可,我們直接繼承原來的類,對需要修改的地方 進行修改,已滿足我們的需求。

歡迎關注我的個人公眾號