随着自动化测试项目复杂度提升,脚本中页面操作会变得越来越混乱,维护成本大幅上升。此时,我们需要一种结构化的管理方式——页面对象模型(Page Object Model,POM)。
💡 什么是 POM?
POM 是一种测试设计模式,将每个页面封装成一个类,页面中的元素作为类的属性,操作动作作为类的方法。
📌 优点:
- 提升代码复用性和可维护性
- 页面变更时只需维护对应类
- 脚本更清晰易懂,测试逻辑和页面结构分离
🧱 POM 基础结构
project/
├── pages/ # 页面对象类
│ ├── login_page.py
│ └── dashboard_page.py
├── tests/ # 测试用例
│ └── test_login.py
├── utils/ # 工具类(等待封装等)
│ └── base_page.py
└── conftest.py # pytest 配置
🧩 1. 基础封装类(BasePage)
# utils/base_page.py
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
class BasePage:
def __init__(self, driver):
self.driver = driver
def wait_visible(self, locator, timeout=10):
return WebDriverWait(self.driver, timeout).until(EC.visibility_of_element_located(locator))
def click(self, locator):
self.wait_visible(locator).click()
def input_text(self, locator, text):
elem = self.wait_visible(locator)
elem.clear()
elem.send_keys(text)
📄 2. 页面类(以登录页为例)
# pages/login_page.py
from selenium.webdriver.common.by import By
from utils.base_page import BasePage
class LoginPage(BasePage):
USERNAME = (By.ID, "username")
PASSWORD = (By.ID, "password")
SUBMIT = (By.ID, "login-btn")
def login(self, username, password):
self.input_text(self.USERNAME, username)
self.input_text(self.PASSWORD, password)
self.click(self.SUBMIT)
🧪 3. 测试用例调用
# tests/test_login.py
from pages.login_page import LoginPage
from selenium import webdriver
def test_login_success():
driver = webdriver.Chrome()
driver.get("https://example.com/login")
login_page = LoginPage(driver)
login_page.login("admin", "123456")
assert "Dashboard" in driver.title
driver.quit()
🧨 POM 结构常见问题
问题 | 解决方法 |
---|---|
元素定位重复 | 放在页面类常量中统一管理 |
操作方法过长 | 拆分为多个小方法 |
多个页面操作混杂 | 每个页面对应一个类,清晰分层 |
每次都要写显式等待 | 抽象进 BasePage,封装 wait_* 方法 |
🧼 小结
- 每个页面对应一个类,元素 + 操作封装在一起
- 测试脚本不再关心定位细节,只关注“动作逻辑”
- 后期维护时只需要修改页面类,不需要改测试代码
📌 推荐进阶实践
pytest + allure
结合 POM 构建完整测试框架- 页面元素配置可使用 YAML / JSON 提取
- BasePage 支持日志记录、截图、重试机制等功能扩展