重复执行用例
引入
在测试过程中我们可能将某条用例,某个测试用例甚至整个测试重复执行多次。这时你可能会想到多写几次运行函数,再不就写个for循环。其实pytest提供了一个扩展模块:pytest-repeat。
安装
pytest-repeat是Python的扩展模块,使用pip命令安装即可。
pip install pytest-repeat
@pytest.mark.repeat()
我们可以用@pytest.mark.repeat()标签修饰测试用例,来实现该用例的重复执行。
吃个小荔枝:我们用@pytest.mark.repeat()修饰测试用例,传入必选参数:重复执行的次数。
#test_Pytest.py文件
#coding=utf-8
import pytest
class Test_Pytest():
def test_one(self):
print("test_one方法执行" )
assert 1==1
@pytest.mark.repeat(2)
def test_two(self):
print("test_two方法执行" )
assert "o" in "love"
def test_three(self):
print("test_three方法执行" )
assert 3-2==1
if __name__=="__main__":
pytest.main(['-s','-v','test_Pytest.py'])
运行结果如下图所示:可以看到被装饰的用例执行了两次。
如果你想重复执行测试类,直接用@pytest.mark.repeat()标签装饰该测试类即可。需要知道的是,执行顺序是第一个用例执行N次,再执行下一个用例N次;而不是每个用例执行一次,共执行N轮。
如果你想重复执行测试模块(.py文件),直接在模块上方(导入pytest包下面)加入下面一行代码即可:pytestmark变量名是固定的~
pytestmark=pytest.mark.repeat(2)
–count 和 --repeat-scope
除了上述通过标签实现重复执行用例,还可以通过命令或运行函数中传入 –count 的方式来实现。
上荔枝:我们在运行函数(或命令行)中传入了参数: --count==执行次数 。
#test_Pytest.py文件
#coding=utf-8
import pytest
class Test_Pytest():
def test_one(self):
print("test_one方法执行" )
assert 1==1
def test_two(self):
print("test_two方法执行" )
assert "o" in "love"
def test_three(self):
print("test_three方法执行" )
assert 3-2==1
if __name__=="__main__":
pytest.main(['-s','-v','--count=2','test_Pytest.py'])
运行结果如下图:我们看到执行的每一个用例都执行了多次。
细心的你可能会发现这个运行顺序还是第一个用例执行N次,再执行下一个用例N次。那如果想要每个用例执行一次,共执行N轮要怎么做呢?这就引出了–repeat-scope参数。
–repeat-scope参数有四个值可供选择,我们来一一学习一下:
- function:以测试用例为单位,将测试用例重复执行N次;在执行下一个用例
- class:以测试类为单位,将类中的每个用例依次执行一遍,共执行N轮;再执行下一个测试类
- module:以模块为单位,将模块中的每个用例依次执行一遍,共执行N轮;再执行下一个模块
- session:以整个测试会话为单位,将会话中的每个用例依次执行一遍;共执行N轮
吃个小荔枝:我们传入参数: --repeat-scope,并设置他的值。这里我们令他为session。
#test_Pytest.py文件
#coding=utf-8
import pytest
class Test_Pytest():
def test_one(self):
print("test_one方法执行" )
assert 1==1
def test_two(self):
print("test_two方法执行" )
assert "o" in "love"
def test_three(self):
print("test_three方法执行" )
assert 3-2==1
if __name__=="__main__":
pytest.main(['-s','-v','--count=2','--repeat-scope=session','test_Pytest.py'])
运行结果如下图:是不是就实现了每个用例执行一次,共执行N轮呢?因为我们的荔枝只是一个测试类,所以参数值用class 和module 也可以实现。
分布式执行测试
引入
如果测试用例过多,执行完成需要很长时间。我们可能需要将测试分成多个部分,并行执行测试,这样可以大大缩短测试时间。pytest也支持这种操作,需要用到pytest-xdist模块。
安装
pytest-xdist是python的扩展模块,使用pip安装即可。
pip install pytest-xdist
使用
使用起来也比较简单,我们模拟多cpu并行测试,在运行函数或命令行加个参数:-n ,后面设置并行的数量即可。
小荔枝:为了较好的展示出分布式测试的效果,我们在每个测试用例中都等待了3秒;在运行函数传入了参数:-n,并设置其值为3。
#文件名是test_firstFile.py
#coding=utf-8
import pytest
import time
class Test_Pytest():
def test_one(self):
print("test_one方法执行" )
time.sleep(3)
assert 1==1
def test_two(self):
print("test_two方法执行" )
time.sleep(3)
assert "o" in "love"
def test_three(self):
print("test_three方法执行" )
time.sleep(3)
assert 3-1==2
if __name__=="__main__":
pytest.main(['-s','-v','-n','3','test_firstFile.py'])
使用并行测试的结果图:我们可以看到运行的时间是4.59秒。
正常运行测试的结果图如下:运行时间是9.19秒
相比而言,使用分布式执行测试大大提高了我们的执行测试的效率。
–looponfail
pytest-xdist还提供参数:–looponfail。其作用是当你执行完测试之后,他会自动监听你的代码修改。如果你的代码有错误,你修改之后保存,他便会自动再运行一遍测试;如果你运行后的结果没有失败或错误,你可能需要手动停止测试。
使用方式:在运行函数或命令行传入参数: --looponfail 即可。
小荔枝:我们故意将第二个用例断言失败;在运行函数传入–looponfail。
#文件名是test_firstFile.py
#coding=utf-8
import pytest
import time
class Test_Pytest():
def test_one(self):
print("test_one方法执行" )
time.sleep(3)
assert 1==1
def test_two(self):
print("test_two方法执行" )
time.sleep(3)
assert "s" in "love"
def test_three(self):
print("test_three方法执行" )
time.sleep(3)
assert 3-1==2
if __name__=="__main__":
pytest.main(['-s','-v','-n','3','--looponfail','test_firstFile.py'])
其运行结果如下图:我们可以看到第二个测试用例执行失败,测试等待修改。。。
我们将用例断言修改正确并保存文件,你会发现测试会自动重新执行。这里不再展示,可自行体会~