在Pytest框架中使用Python Selenium实现登录测试动态凭证持久化
解决方案:全局复用生成的登录凭证
问题根源
- 当前Helper类在定义阶段就直接生成随机凭证,每次导入Helper类(比如不同测试套件导入时)都会重新生成新值,导致凭证不断变化。
- 缺少凭证初始化的判断逻辑,无法确保只生成一次凭证。
修复后的Helper类
修正语法错误,调整凭证生成逻辑,确保仅在需要时生成并持久化:
import uuid class Helper: # 初始化类变量为None,标记未生成状态 user_name = None user_email = None user_password = None USER_INFO_FILE = 'user_name_info.txt' @classmethod def generate_and_save_user_info(cls): # 仅当凭证未生成时才生成新值 if cls.user_name is None: random_mail = f'tester{str(uuid.uuid4())[:5]}@example.com' # 补全邮箱后缀,避免split报错 cls.user_name = random_mail.split("@")[0] cls.user_email = random_mail cls.user_password = f'Pa#{str(uuid.uuid4())[:10]}' # 保存到文件,作为备用复用方案 cls.create_user_info_file() return cls.get_user_info() @classmethod def create_user_info_file(cls): with open(cls.USER_INFO_FILE, 'w') as file: file.write(f'{cls.user_name}\n{cls.user_email}\n{cls.user_password}') @classmethod def read_user_info_file(cls): # 从文件读取,用于测试重启后的复用(可选) try: with open(cls.USER_INFO_FILE, 'r') as file: lines = file.readlines() cls.user_name = lines[0].strip() cls.user_email = lines[1].strip() cls.user_password = lines[2].strip() return cls.get_user_info() except FileNotFoundError: # 文件不存在则生成新凭证 return cls.generate_and_save_user_info() @classmethod def get_user_info(cls): return { 'user_name': cls.user_name, 'user_email': cls.user_email, 'user_password': cls.user_password }
用Pytest Fixture全局管理凭证和登录状态
在conftest.py中定义会话级别的fixture,确保凭证只生成一次,所有测试复用:
import pytest from selenium import webdriver from your_module import Helper # 替换为你的Helper类所在模块 @pytest.fixture(scope="session") def user_credentials(): # 优先从类变量获取,无则生成/读取 if Helper.user_name is None: Helper.generate_and_save_user_info() return Helper.get_user_info() @pytest.fixture(scope="session") def logged_in_driver(user_credentials): driver = webdriver.Chrome() # 根据你的浏览器配置调整 # 执行登录逻辑 driver.get("your_login_page_url") driver.find_element("id", "username").send_keys(user_credentials['user_name']) driver.find_element("id", "password").send_keys(user_credentials['user_password']) driver.find_element("id", "login-btn").click() # 等待登录完成(可根据实际情况添加显式等待) yield driver # 测试结束后关闭浏览器 driver.quit()
测试用例写法
test_suit_01/test_01.py(第一个测试,触发凭证生成)
from your_module import Helper def test_01_generate_credentials_and_login(logged_in_driver): # logged_in_driver fixture会自动触发凭证生成和登录 # 这里可添加登录后的验证逻辑,比如检查用户名是否显示 assert logged_in_driver.find_element("id", "current-user").text == Helper.user_name
其他测试套件(比如test_suit_02/test_02.py)
def test_02_user_profile(logged_in_driver, user_credentials): # 直接使用已登录的driver和全局凭证 logged_in_driver.get("your_profile_page_url") assert logged_in_driver.find_element("id", "profile-email").text == user_credentials['user_email']
关键说明
- 会话级Fixture:
scope="session"确保user_credentials和logged_in_driver在整个pytest会话中只执行一次,所有测试复用同一个凭证和登录状态。 - 类变量判断:Helper类中通过
if cls.user_name is None确保凭证仅生成一次,避免重复覆盖。 - 文件持久化:可选保留文件读写逻辑,用于测试会话重启后复用同一凭证(如果需要)。
内容的提问来源于stack exchange,提问作者Anton Shatz
相关产品推荐
相关产品推荐

