Playwright 自动化测试系列(7)| 第三阶段:测试框架集成Page Object 模式
一、Page Object 模式的核心价值
1. 问题驱动
传统测试脚本将元素定位与操作逻辑混写在用例中,导致:
- 维护灾难:页面元素变动需修改所有相关用例(如登录按钮ID变更需全局搜索替换)
- 复用困难:相同操作逻辑无法跨用例共享(如登录流程重复编写)
- 可读性差:业务逻辑被技术细节淹没(如page.locator(“#login-btn”).click()分散在多个步骤)
2. 解决方案
Page Object(PO)模式将页面抽象为类:
- 元素定位器 → 封装为类属性
- 操作行为 → 封装为类方法
- 业务流 → 通过方法组合实现
# 传统模式 vs PO模式对比 # 传统:元素定位与操作耦合 page.locator(\"#username\").fill(\"user1\") page.locator(\"#password\").fill(\"pass1\") page.locator(\"#login-btn\").click() # PO模式:业务语义化 login_page.enter_username(\"user1\") login_page.enter_password(\"pass1\") login_page.click_login()
二、电商全流程PO架构设计
1. 系统分层架构
2. 核心类设计
三、实战:电商登录-下单PO封装
1. 登录页封装(LoginPage)
class LoginPage: def __init__(self, page): self.page = page self.username_input = page.get_by_placeholder(\"手机号/邮箱\") # 使用面向用户定位器 self.password_input = page.get_by_label(\"密码\") self.submit_btn = page.get_by_role(\"button\", name=\"登录\") def navigate_to_login(self): self.page.goto(\"https://mall.example.com/login\") def enter_credentials(self, username, password): self.username_input.fill(username) self.password_input.fill(password) def submit(self): self.submit_btn.click() self.page.wait_for_url(\"**/dashboard\") # 显式等待导航完成
2. 购物车页封装(CartPage)
class CartPage: def __init__(self, page): self.page = page self.coupon_field = page.locator(\"[data-testid=\'coupon-input\']\") # 测试ID定位增强稳定性 self.apply_btn = page.get_by_text(\"应用优惠券\") def apply_coupon(self, code: str): self.coupon_field.fill(code) self.apply_btn.click() expect(self.page.get_by_text(\"优惠券已生效\")).to_be_visible() # 自动等待 + 断言 def checkout(self): self.page.get_by_role(\"button\", name=\"结算\").click()
3. 业务流组合(测试用例层)
def test_e2e_order(login_page, home_page, cart_page): # 登录 → 搜索 → 加购 → 结算 login_page.navigate_to_login() login_page.enter_credentials(\"user1\", \"securePass123\") login_page.submit() home_page.search_product(\"无线耳机\") home_page.select_first_product() product_page.add_to_cart(quantity=2) cart_page.apply_coupon(\"FESTIVAL2025\") cart_page.checkout() order_page.confirm_payment() assert order_page.get_order_status() == \"支付成功\"
四、PO模式高级技巧
1. 复合操作封装
避免原子操作暴露,直接提供业务接口:
# 反例:调用方需知道操作细节 login_page.enter_username(\"user1\") login_page.enter_password(\"pass1\") login_page.click_login() # 正例:业务语义封装 login_page.login_with(\"user1\", \"pass1\")
2. 动态元素处理
使用Playwright的Locator API处理动态生成元素:
def get_product_element(self, name): return self.page.locator(f\".product-item:has-text(\'{name}\')\") # 文本+CSS组合定位
3. 多层级PO复用
通过页面嵌套实现复杂组件复用:
class HeaderComponent: def __init__(self, page): self.search_bar = page.get_by_role(\"searchbox\") def search(self, keyword): self.search_bar.fill(keyword) self.search_bar.press(\"Enter\") class HomePage: def __init__(self, page): self.page = page self.header = HeaderComponent(page) # 复用头部组件
五、Pytest集成与多用户测试
1. 测试隔离设计
利用Playwright的browser.new_context()实现用户会话隔离:
# conftest.py @pytest.fixture(scope=\"function\") def user_context(playwright): browser = playwright.chromium.launch() context = browser.new_context(storage_state=\"user1_session.json\") # 复用登录态 yield context context.close()
2. 多用户并发测试
模拟用户并发抢购场景:
def test_concurrent_purchase(user_context_factory): with ThreadPoolExecutor() as executor: # 启动3个并发用户 futures = [ executor.submit(run_user_flow, user_context_factory(\"user1\")), executor.submit(run_user_flow, user_context_factory(\"user2\")), executor.submit(run_user_flow, user_context_factory(\"user3\")) ] results = [f.result() for f in futures] assert all(\"下单成功\" in r for r in results)
六、常见问题解决方案
七、总结:PO模式的核心收益
可维护性:页面变更只需修改对应PO类,不影响200+测试用例
可读性:用例清晰表达业务意图(login_page.login_with() vs 5行定位代码)
复用性:购物车操作复用率达90%(加购/改数量/结算等)
扩展性:通过组件化设计支持新页面快速接入
终极实践建议:
原子操作 → 封装在PO方法内
业务流程 → 组合PO方法实现
验证逻辑 → 通过expect断言集成
环境隔离 → 善用browser.new_context()
通过本实战,可构建日均执行5000+用例的电商测试框架,缺陷捕捉率提升40%,维护成本降低70%。
Playwright学习交流群
推荐阅读:
Playwright 自动化测试系列(6)| 第三阶段:测试框架集成指南:参数化测试 + 多浏览器并行执行
Playwright自动化测试系列课(5) | 调试神器实战:Trace Viewer 录屏分析 + AI 辅助定位修复
Playwright自动化测试系列课(4) | 异步加载克星:自动等待 vs 智能等待策略深度解析
Playwright自动化测试系列课(3) | 第二阶段:核心技能与调试 交互操作大全
Playwright系列课(2) |元素定位四大法宝:CSS/文本/XPath/语义化定位实战指南
Playwright 极速入门:1小时搞定环境搭建与首个测试脚本
Playwright-MCP浏览器会话复用全解析
Agent的深度解析:从原理到实践
Kimi K2开源炸场,1万亿参数碾压GPT-4.1,成本仅Claude 4的1/5!
10+热门 AI Agent 框架深度解析:谁更适合你的项目?