前言:
试想一下1000条用例,每条用例1s全部线性执行下来都要十几分钟, 如果改用多线程执行,开十个线程一分多钟就可以搞定, 这是多大诱惑。啃了几天终于也是拿下了多线程,虽然学会了,最终却发现项目上不适用,无奈下只能放弃。
如何使用多线程?
安装:pip install pytest-xdist
使用1:-n=线程数
import pytest
class TestCase:
def test_001(self):
print('用例1')
def test_002(self):
print('用例2')
def test_003(self):
print('用例3')
if __name__ == '__main__':
pytest.main(['-s', '-n=3', '--dist=loadscope', './test_001.py'])
执行结果:
gw0 I / gw1 I / gw2 I
gw0 [3] / gw1 [3] / gw2 [3]
...
执行结果解析:使用多线程不会打印程序内容 gw0 I / gw1 I / gw2 I 说明它起了三个线程, gw2 [3] 这个 [3] 说明有三条用例, ...三个点说明三条用例都执行成功
使用2:-n=auto
if __name__ == '__main__':
pytest.main(['-s', '-n=auto', './test_001.py'])
执行结果:
gw0 I / gw1 I / gw2 I / gw3 I / gw4 I / gw5 I
gw0 [3] / gw1 [3] / gw2 [3] / gw3 [3] / gw4 [3] / gw5 [3]
...
执行结果解析:系统自动根据CPU核心分配线程数来执行用例,我的电脑是6核心,它分配了5个线程来执行,另外的那个被别的程序占用了。
多线程它分三种执行方式:
--dist=loadscope:按模块来执行用例,也就是一个线程执行一个模块(class)
--dist=loadfile:按测试文件执行用例,也就是一个线程执行一个测试文件(file)
默认顺序:如果什么都不写, 则默认是以单独的测试用例来执行,也就是一个线程执行一个用例(case)
使用方式:
if __name__ == '__main__':
pytest.main(['-s', '-n=auto', '--dist=loadscope', './test_001.py'])
知道是这么使用就可以了,执行结果就不解析了
问题:
问题1:conftest.py文件里的内容, 也被多次执行了, conftest.py放的是登录等前后置方法,多次执行这不是我想要的,怎么解决?请看以下conftest.py文件中的代码,有注释,很简单, 直接套用就行。
将以下代码复制粘贴到conftest.py文件中,“print('写你的函数方法,例如:登录')” 标记有这个的地方,就是可以修改的地方,其余地方不能修改
import json
import pytest
from filelock import FileLock
# PC端登录
@pytest.fixture(autouse=True, scope="session")
# tmp_path_factory, worker_id: 不用修改传递的这两个参数,这里是固定写好的。函数名称可以自定义【不可删除,修改】
def login_request(tmp_path_factory, worker_id):
# 如果是单线程执行,则走该分支【不可删除、修改】
if worker_id == "master":
print('写你的函数方法,例如:登录')
# 如果是多线程执行,则走以下分支:获取所有子节点共享的临时目录【不可删除、修改】
root_tmp_dir = tmp_path_factory.getbasetemp().parent
# 生成一个临时文件给所有进程用【不可删除、修改】
fn = root_tmp_dir / "data.json"
with FileLock(str(fn) + ".lock"):
# 当第2个及以后的进程执行用例时,走到这个分支【不可删除、修改】
if fn.is_file():
pass
# 第1个进程走到这里,将生成的数据存到共享文件中
else:
# 登录方法_pc
data = print('写你的函数方法,例如:登录')
fn.write_text(json.dumps(data))
好了, 来说明一下为啥不建议使用多线程了
使用多线程时, 你的用例之间的依赖必须是独立的,就是用例1不能用用例2的变量,否则执行就会出现异常,其实这一条规则足以将大部分学者劝退,因为项目上不可能一条用例分配一个测试账号来设计。