Playwright:PageObject函数传定位器参数及POM实现方法
解决Playwright Page-Object Model中Locator的定义问题及优化方案
一、你的现有代码问题及修复方式
你当前的核心问题是:类级别无法直接定义Locator对象——因为Login类的类变量初始化时,还没有创建page实例,没法调用self.page.locator()。下面提供两种可行的修复方案:
方案1:将Locator定义为实例属性(推荐)
在Login类的__init__方法中,调用父类初始化后,再用page实例创建Locator:
class BasePage: def __init__(self, page): self.page = page def open_page(self, url): self.page.goto(url) def enter_text(self, locator, text): locator.fill(text) class Login(BasePage): URL = 'http://example.com/auth/login/' def __init__(self, page): super().__init__(page) # 替换成你页面实际的选择器(id/CSS/XPath都可以) self.login_locator = self.page.locator("#username") self.password_locator = self.page.locator("#password") def login(self, login, password): self.open_page(self.URL) self.enter_text(self.login_locator, login) self.enter_text(self.password_locator, password) self.password_locator.press('Enter') def is_login_success(self): # 实现登录成功的校验逻辑,比如检查URL或元素可见性 return self.page.url == "http://example.com/dashboard/"
对应的测试用例可以简化为实例调用(更符合POM规范):
def test_login_success(page: Page): login_page = Login(page) login_page.login('admin', 'admin') assert login_page.is_login_success()
方案2:修改BasePage,让enter_text接收选择器字符串
如果想把选择器保留为类变量,可以调整BasePage的方法,直接接收选择器字符串而非Locator对象:
class BasePage: def __init__(self, page): self.page = page def open_page(self, url): self.page.goto(url) def enter_text(self, selector, text): # 直接通过选择器获取Locator并填充文本 self.page.locator(selector).fill(text) class Login(BasePage): URL = 'http://example.com/auth/login/' # 定义选择器字符串为类变量 login_selector = "#username" password_selector = "#password" def login(self, login, password): self.open_page(self.URL) self.enter_text(self.login_selector, login) self.enter_text(self.password_selector, password) self.page.locator(self.password_selector).press('Enter') def is_login_success(self): return self.page.url == "http://example.com/dashboard/"
测试用例同样改为实例调用即可。
二、Playwright官方推荐的POM实现方式
Playwright官方更推荐去掉通用BasePage,让每个页面类独立封装自身元素和操作,这样职责更清晰,维护更方便:
from playwright.sync_api import Page class LoginPage: def __init__(self, page: Page): self.page = page self.url = "http://example.com/auth/login/" # 直接在初始化时定义页面元素的Locator self.username_input = page.locator("#username") self.password_input = page.locator("#password") self.welcome_message = page.locator(".welcome-text") def load(self): self.page.goto(self.url) def submit_login(self, username: str, password: str): self.username_input.fill(username) self.password_input.fill(password) self.password_input.press("Enter") def is_login_successful(self) -> bool: # 双重校验:URL跳转+欢迎元素可见 return self.page.url == "http://example.com/dashboard/" and self.welcome_message.is_visible()
对应的测试用例:
def test_login_success(page: Page): login_page = LoginPage(page) login_page.load() login_page.submit_login("admin", "admin") assert login_page.is_login_successful()
这种方式的优势是每个页面的元素和操作都封装在自身类中,没有冗余的通用层,更贴合Playwright的原生API设计。
内容的提问来源于stack exchange,提问作者Egor
相关产品推荐
相关产品推荐

