在前面的介紹中陈症,我們對unittest進行了分享介紹蔼水,那么在實際的應(yīng)用中,因為客觀原因需要對失敗录肯,錯誤的測試用例進行重試趴腋,所以呢,現(xiàn)有的unittest的框架無法滿足,那么我們可以去改造下是否能夠滿足呢优炬。本文帶領(lǐng)大家去剖析如何改寫颁井?
首先呢,我們?nèi)ピ囍フ蚁麓┢剩覀冞\行時在BSTestRunner蚤蔓、TextTestRunner或者main,都可以執(zhí)行用例糊余,那么我們可以看下這些類或者方法里面如何實現(xiàn)的秀又。
BSTestRunner調(diào)用方式如下
TextTestRunner的方法是,
使用main方法最后的調(diào)用也是這個函數(shù)贬芥。詳細的我們可以看下吐辙,首先調(diào)用這個函數(shù),然后在看實際的調(diào)用.
最后的調(diào)用也是這個函數(shù)
所以我們就要在里面的方法去查找適合我們使用的方法蘸劈。
在注釋中昏苏,我們可以發(fā)現(xiàn)在stopTest的方法中可以對其進行改寫。
def stopTest(self, test):
"""Called when the given test has been run"""
self._restoreStdout()
self._mirrorOutput = False
那么我們應(yīng)該如何改寫呢威沫,我們梳理下我們的思路贤惯。
- 1.傳遞重試次數(shù),默認不需要重試
- 2.在用例執(zhí)行的錯誤棒掠,標(biāo)記為需要重試
- 3.在該條用例執(zhí)行完畢后孵构,我們判斷是否需要重試,重試次數(shù)是否滿足
- 4.如果需要重試烟很,則保存最新的從測試結(jié)果颈墅。
那么我們開始按照上面的思路進行改造。
代碼如下
import sys,copy
from io import StringIO as StringIO
TestResult = unittest.TestResult
class MyResult(TestResult):
def __init__(self, verbosity=1, trynum=0):
#默認次數(shù)是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 :
#如果執(zhí)行的次數(shù)小于重試的次數(shù) 就重試
if self.trys < self.trynnum :
#刪除最后一個結(jié)果
reslut = self.result.pop(-1)
#判斷結(jié)果雾袱,如果是錯誤就把錯誤的個數(shù)減掉
#如果是失敗恤筛,就把失敗的次數(shù)減掉
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)
#重試次數(shù)增加+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,錯誤次數(shù)+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)
執(zhí)行的結(jié)果如下:
目前改造滿足我們重試用例的需求粘驰,改造完畢。
上面只是一個簡單的改造述么,滿足了對于失敗的測試用例的重試蝌数,其實很簡單,我們有了需求度秘,去根據(jù)我們的需求去查找需要改造的代碼即可顶伞,我們直接繼承原來的類饵撑,對需要修改的地方 進行修改,已滿足我們的需求唆貌。