什么是重跑机制
如果用例执行失败,那么可以对这个用例执行多次,直到它成功为止。
unitest基本原理
要完成unitest扩展,肯定需要对unitest基本原理简单了解, 这里用流程图来解释unitest执行步骤比较清楚。
1.首先执行setupClass(这里不重要,不做说明)
2.执行test1用例前的setup
3.执行test1
4.执行test1用例后的teardown
5.最后执行teardownClass(这里不重要,不做说明)
tips:
1.这里只有画了了一个用例test1, 其实实际有很多用例。
2.每一个用例都要先执行**setup**后执行**teardown**
3.**setup**、**test1**、**teardown**可以看成一个整体。
代码
from unittest import TestCase, main
class Test(TestCase):
@classmethod
def setUpClass(cls) -> None:
print('1.---------setUpClass---------')
def setUp(self) -> None:
print('2.---------setUp---------')
def test1(self):
print('3.--------执行test1----')
def tearDown(self) -> None:
print('4.---------tearDown---------')
@classmethod
def tearDownClass(cls) -> None:
print('5.---------tearDownClass---------')
'''
执行结果
1.---------setUpClass---------
2.---------setUp---------
3.--------执行test1----
4.---------tearDown---------
5.---------tearDownClass---------
'''
if __name__ == '__main__':
main()
重跑机制伪代码
我们以上面的流程图为例,假设test1执行失败,会怎么办呢???
按照上面所说的无非就是运行setup、test1、teardown呗。
这里来我们展示伪代码
重跑机制-编码
首先想好几个问题???
- 如果重跑一直失败怎么办,是否要添加重跑次数?
- test1这个用例函数,我们不能在里面在for、while方式进行对它用例重跑,这样显得代码很难看,我们规定说test1这个函数里面只有这个用例一些基本信息、步骤、断言等。
先回答第二个问题用修饰器,不改变原来test1函数的代码上进行拓展。
第一个问题只要修饰器函数里添加一个参数num来代表重跑次数。
我们不断在文章中提到setup、test1、teardown可以看成一个整体,当test1进行重跑时,必须要执行setup和teardown;所以要把setup和teardown作为修饰器函数的参数。
from unittest import TestCase, main
from functools import wraps
def re_run(num, setup, teardown):
def wrapped(func):
@wraps(func)
def inner(*args, **kwargs):
self = args[0]
for i in range(num):
if i > 0:
print(func.__name__, '重跑', i, '次')
else:
print(func.__name__, '第一次执行')
try:
func(*args, **kwargs)
return
except Exception:
teardown(self)
setup(self)
raise Exception(func.__name__, '用例失败了')
return inner
return wrapped
class Test(TestCase):
@classmethod
def setUpClass(cls) -> None:
print('1.---------setUpClass---------')
def setUp(self) -> None:
print('2.---------setUp---------')
def tearDown(self) -> None:
print('4.---------tearDown---------')
@re_run(1, setUp, tearDown)
def test1(self):
assert 1 == 2
@classmethod
def tearDownClass(cls) -> None:
print('5.---------tearDownClass---------')
if __name__ == '__main__':
main()