Page Object Model 详解
架构图
👤 用户
→
🎯 测试框架 (pytest)
→
📄 Page Objects
→
⚙️ Selenium Driver
→
🌐 浏览器
→
🏢 Web 应用
项目目录结构
project/
├── pages/ # 页面对象层
│ ├── base_page.py # 基础页面对象
│ ├── login_page.py # 登录页面
│ ├── home_page.py # 首页
│ └── register_page.py # 注册页面
├── tests/ # 测试用例层
│ ├── conftest.py # pytest 配置
│ ├── test_login.py
│ └── test_register.py
├── data/ # 测试数据
│ └── test_data.yaml
├── utils/ # 工具类
│ ├── driver_factory.py
│ └── logger.py
├── reports/ # 测试报告
└── requirements.txt
BasePage 实现
from selenium.webdriver.common.by import By
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
self.wait = WebDriverWait(driver, 10)
def click(self, locator):
self.wait.until(EC.element_to_be_clickable(locator)).click()
def input(self, locator, text):
el = self.wait.until(EC.presence_of_element_located(locator))
el.clear()
el.send_keys(text)
def get_text(self, locator):
return self.wait.until(EC.presence_of_element_located(locator)).text
def is_element_visible(self, locator):
try:
self.wait.until(EC.visibility_of_element_located(locator))
return True
except:
return False
def switch_to_frame(self, locator):
iframe = self.wait.until(EC.presence_of_element_located(locator))
self.driver.switch_to.frame(iframe)
LoginPage 示例
from selenium.webdriver.common.by import By
from pages.base_page import BasePage
class LoginPage(BasePage):
USERNAME_INPUT = (By.ID, "username")
PASSWORD_INPUT = (By.ID, "password")
LOGIN_BUTTON = (By.ID, "loginBtn")
FORGOT_LINK = (By.ID, "forgotPwd")
def login(self, username, password):
self.input(self.USERNAME_INPUT, username)
self.input(self.PASSWORD_INPUT, password)
self.click(self.LOGIN_BUTTON)
def login_success(self, username, password):
self.login(username, password)
return self.driver.switch_to.alert()
def get_error_message(self):
return self.driver.switch_to.alert().text
测试用例示例
import pytest
from pages.login_page import LoginPage
class TestLogin:
def test_login_success(self, driver):
login_page = LoginPage(driver)
login_page.driver.get("file:///F:/autotest_project/login.html")
alert = login_page.login_success("admin", "123456")
assert "登录成功" in alert.text
alert.accept()
def test_login_empty(self, driver):
login_page = LoginPage(driver)
login_page.driver.get("file:///F:/autotest_project/login.html")
login_page.click(LoginPage.LOGIN_BUTTON)
error = login_page.get_error_message()
assert "请输入" in error