写点什么

Playwright 自动化测试 | 测试框架集成​​Page Object 模式

作者:测试人
  • 2025-07-28
    北京
  • 本文字数:2405 字

    阅读完需:约 8 分钟

一、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 模式的核心收益

  1. 可维护性:页面变更只需修改对应 PO 类,不影响 200+测试用例

  2. 可读性:用例清晰表达业务意图(login_page.login_with() vs 5 行定位代码)

  3. 复用性:购物车操作复用率达 90%(加购/改数量/结算等)

  4. 扩展性:通过组件化设计支持新页面快速接入

终极实践建议

  • 原子操作 → 封装在 PO 方法内

  • 业务流程 → 组合 PO 方法实现

  • 验证逻辑 → 通过 expect 断言集成

  • 环境隔离 → 善用 browser.new_context()

通过本实战,可构建日均执行 5000+用例的电商测试框架,缺陷捕捉率提升 40%,维护成本降低 70%。

用户头像

测试人

关注

专注于软件测试开发 2022-08-29 加入

霍格沃兹测试开发学社,测试人社区:https://ceshiren.com/t/topic/22284

评论

发布
暂无评论
Playwright 自动化测试 | 测试框架集成​​Page Object 模式_软件测试_测试人_InfoQ写作社区