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