unittest系统(八)一文搞定unittest重试功能
在前面的介绍中,我们对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)
执行的结果如下:
目前改造满足我们重试用例的需求,改造完毕。
上面只是一个简单的改造,满足了对于失败的测试用例的重试,其实很简单,我们有了需求,去根据我们的需求去查找需要改造的代码即可,我们直接继承原来的类,对需要修改的地方 进行修改,已满足我们的需求。
欢迎关注我的个人公众号