如何在基于fixture初始化driver的pytest类中复用Selenium函数?
如何将复用函数整合到基于pytest fixture的Selenium测试类中
我是自动化测试新手,手里有一些Selenium基础函数想复用,但WebDriver是在pytest的fixture里初始化的,不知道怎么把这些函数整合到测试类里。
现有代码
conftest.py
from selenium.webdriver.chrome.options import Options from selenium import webdriver import pytest import pyautogui import time @pytest.fixture(scope="class") def setup(request): options = Options() options.add_experimental_option("detach", True) # 注意:这行需在初始化driver前设置 driver = webdriver.Chrome(options=options) request.cls.driver = driver url = "你的测试URL" # 补充实际测试地址 username = "你的用户名" # 补充实际账号 password = "你的密码" # 补充实际密码 driver.get(url) driver.maximize_window() pyautogui.typewrite(username) pyautogui.press('tab') pyautogui.typewrite(password) pyautogui.press('enter') time.sleep(3) yield driver.quit() @pytest.mark.usefixtures("setup") class BaseTest: pass
test.py
from selenium.webdriver.common.by import By from conftest import BaseTest buttonDisplayed = [] buttonNotDisplayed = [] buttonEnabled = [] buttonDisabled = [] clickActionPassed = [] class TestLandingPage(BaseTest): def test_profilenav(self): profile = self.driver.find_element(by=By.XPATH, value="/html/body/div[1]/div/div[1]/div[2]/div[3]/div[3]/div[1]/div/a[1]") if profile.is_displayed(): profileDisplayed = "Profile Icon is displayed" print(profileDisplayed) buttonDisplayed.append(profileDisplayed) else: profileNotDisplayed = "Profile Icon is not displayed" print(profileNotDisplayed) buttonNotDisplayed.append(profileNotDisplayed) if profile.is_enabled(): profileEnabled = "Profile button is enabled" print(profileEnabled) buttonEnabled.append(profileEnabled) else: profileDisabled = "Profile button is disabled" print(profileDisabled) buttonDisabled.append(profileDisabled) profile.click() profileClickAction = "Profile passed" print(profileClickAction) clickActionPassed.append(profileClickAction) # 待调用的复用函数 # returnToHome() # profileIcon()
需要复用的函数
import time from selenium.webdriver.common.by import By def returnToHome(): time.sleep(2) logo = driver.find_element(by=By.CSS_SELECTOR, value='[alt="banner"]') if logo.is_displayed(): print("Logo return to home is displayed") else: print("Logo return to home is not displayed") logo.click() time.sleep(2) def profileIcon(): profileIcon = driver.find_element(by=By.XPATH, value="/html/body/div[1]/div/div[1]/div[2]/div[3]") if profileIcon.is_displayed(): print("Profile Icon button is displayed") else: print("Profile Icon button is not displayed") profileIcon.click() print("Profile Icon passed") time.sleep(1)
解决方案
方案1:将复用函数转为BaseTest的实例方法
这种方式最贴合现有测试结构,BaseTest已通过fixture获取self.driver,直接集成到基类即可:
1. 修改conftest.py中的BaseTest类
把复用函数改成BaseTest的实例方法,将函数内的driver替换为self.driver:
@pytest.mark.usefixtures("setup") class BaseTest: def return_to_home(self): time.sleep(2) logo = self.driver.find_element(by=By.CSS_SELECTOR, value='[alt="banner"]') if logo.is_displayed(): print("Logo return to home is displayed") else: print("Logo return to home is not displayed") logo.click() time.sleep(2) def profile_icon(self): profile_icon = self.driver.find_element(by=By.XPATH, value="/html/body/div[1]/div/div[1]/div[2]/div[3]") if profile_icon.is_displayed(): print("Profile Icon button is displayed") else: print("Profile Icon button is not displayed") profile_icon.click() print("Profile Icon passed") time.sleep(1)
注:函数名改为下划线命名,符合Python PEP8编码规范,也可保留原名称
2. 在测试类中调用方法
由于TestLandingPage继承了BaseTest,直接通过self.方法名()调用即可:
class TestLandingPage(BaseTest): def test_profilenav(self): # 原有测试逻辑... # 调用基类中的复用方法 self.return_to_home() self.profile_icon()
方案2:将driver作为参数传入复用函数
如果希望复用函数保持独立(比如放在单独的工具文件中),可以给函数添加driver参数,调用时传入self.driver:
1. 调整复用函数
import time from selenium.webdriver.common.by import By def returnToHome(driver): time.sleep(2) logo = driver.find_element(by=By.CSS_SELECTOR, value='[alt="banner"]') if logo.is_displayed(): print("Logo return to home is displayed") else: print("Logo return to home is not displayed") logo.click() time.sleep(2) def profileIcon(driver): profileIcon = driver.find_element(by=By.XPATH, value="/html/body/div[1]/div/div[1]/div[2]/div[3]") if profileIcon.is_displayed(): print("Profile Icon button is displayed") else: print("Profile Icon button is not displayed") profileIcon.click() print("Profile Icon passed") time.sleep(1)
2. 在测试类中调用函数
# 先导入复用函数 from your_utils_file import returnToHome, profileIcon class TestLandingPage(BaseTest): def test_profilenav(self): # 原有测试逻辑... # 传入self.driver调用函数 returnToHome(self.driver) profileIcon(self.driver)
额外提示
- 原conftest.py中
options.add_experimental_option("detach", True)要放在driver = webdriver.Chrome(options=options)之前,否则设置不生效。 - 避免使用硬编码的绝对XPATH(如
/html/body/...),建议改用更稳定的定位方式(如ID、class或相对XPATH)。
内容的提问来源于stack exchange,提问作者polotop
相关产品推荐
相关产品推荐

