在前面的介紹中,我們對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)
執行的結果如下:
目前改造滿足我們重試用例的需求,改造完畢。
上面只是一個簡單的改造,滿足了對於失敗的測試用例的重試,其實很簡單,我們有了需求,去根據我們的需求去查詢需要改造的程式碼即可,我們直接繼承原來的類,對需要修改的地方 進行修改,已滿足我們的需求。
歡迎關注我的個人公眾號