场景
在UI自动化项目中,使用的是pytest + playwright, 需要实现同一个用户只登录一次的,所以在conftest.py中定义了一个scope=session的fixture,然后在此fixture中实现了系统登录,在非并发模式下执行的时候,能保证同一个用户只登录一次,但是并发执行的时候每个case都会执行登录
问题
需要解决并发执行的时候同一个用户只登录一次,如果是不同用户的时候还是需要进行登录
解决方法
- pytest-xdist官方给出的解决方案:https://pytest-xdist.readthedocs.io/en/stable/how-to.html#making-session-scoped-fixtures-execute-only-once
- 参考pytest-xdist给出的解决方案实现如下:
import pytest
from filelock import FileLock
from os import path
import os
@pytest.fixture(scope="session", autouser=True)
def login_session(browser, browser_context_args, session_file, worker_id):
'''
1. 并发执行情况下,同一个user不需要多次登录
2. 不同的用户还需要登录
3. session_file是自定义的fixture,定义了用户登录信息存储的文件路径
'''
logging.debug("worker_id:%s" % worker_id)
if path.exists(session_file) and worker_id == "master":
logging.info("session file已存在,用户已登录") # session文件已存在,不需要登录
with FileLock(str(session_file) + ".lock"): #FileLock实现只登录一次
if session_file.is_file():
logging.info("session file已存在") # session 文件已存在,需要登录
else:
logging.info("用户进行登录操作")
browsercontext = browser.new_context(**browser_context_args)
login(browsercontext, request, session_file) # 函数定义了登录操作,并且登录成功后存储用户的session文件
# session文件路径的定义
@pytest.fixture(scope="session")
def set_session_file(user, tmp_path_factory, test_data):
'''
1.设置登录后的session保存位置, 通过tmp_path_factory设置临时目录
'''
logging.info(f"登录用户:{user}")
# 这里取的临时目录的getbasetemp().parent,因为并发时getbasetemp获取每个case路径是类似temp_dir/gw0, temp_dir/gw1,所以为了保证存放session的路径是同一个路径;
#当然这里也可以创建一个目录来存放session,不过要在login_session的fixture中添加yield并且在yield后添加删除session file,避免session失效的情况, 使用临时目录会自动删除
if "gw" in path.split(tmp_path_factory.getbasetemp())[-1]: #并发执行的路径取值
dir= tmp_path_factory.getbasetemp().parent
else: 非并发执行的时候路径取值
dir = tmp_path_factory.getbasetemp()
session_file = path.join(dir, "session_files", "%s.json" % user)
logging.info('session file is:%s'%session_file)
return Path(session_file)