Help us improve
Share bugs, ideas, or general feedback.
From velocitai
Guides POM (Page Object Model) layering and context sharing decisions for Playwright test suites. Helps determine base class design, page object structure, and when to share browser context across tests.
npx claudepluginhub danielsuo117/velocitai --plugin velocitaiHow this skill is triggered — by the user, by Claude, or both
Slash command
/velocitai:architectureThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
- 新增角色/端时决定是否引入新基类
Guides creating page objects and refactoring Playwright tests using Page Object Model patterns for maintainability, reusability, and scalability. Covers locators, principles, and TypeScript examples.
Writes new Playwright E2E tests following project conventions, with POM/business-layer architecture, network-aware stability patterns, and quality validation.
Expert approach to page-object-model in test automation. Use when working with .
Share bugs, ideas, or general feedback.
┌─────────────────────────────────────────────┐
│ tests/ 测试层 │
│ 按角色拆分文件:test_<role>_flow.py │
│ 每个测试类继承 Base(或 Role-Base) │
├─────────────────────────────────────────────┤
│ pages/ 页面对象层 │
│ Base ← Login ← Landing ← Detail / ... │
│ 通用 Role 用前缀命名:Role<Role><Page>Page │
├─────────────────────────────────────────────┤
│ config/ 配置层 │
│ URL、Token、浏览器参数按环境切换 │
├─────────────────────────────────────────────┤
│ conftest.py Fixture 层 │
│ browser → context → page → Role-specific base │
└─────────────────────────────────────────────┘
数据流向:config → conftest(读取配置创建 fixture) → pages(接收 page 对象) → tests(组合页面对象执行断言)
# 页面名称:<中文名>
from pages.base_page import BasePage
class <PageName>(BasePage):
# 定位符常量(类顶部)
<LOCATOR_CONSTANT> = "<selector>" # P<0-5>: 说明
PAGE_IDENTIFIER = "<selector>" # 页面加载锚点
# 业务方法(前缀:click_ / fill_ / select_ / get_xxx_text / wait_for_ / is_xxx_visible)
def click_<action>(self):
self.click(self.<LOCATOR_CONSTANT>)
# 页面加载验证(必须实现,放在最后)
def is_page_loaded(self) -> bool:
return self.is_visible(self.PAGE_IDENTIFIER)
一组用例是否满足以下 3 条?
1. 同一域名(不跨端)
2. 有统一前置(登录、角色切换…)
3. 有统一起点页面(可复位)
│
├─ 是(三条全满足)
│ └→ class 级共享 context
│ - 用 scope="class" 的 page fixture(实现见 browser-config skill)
│ - 专用基类:class setup 完成前置;function-scope autouse 复位起点
│ - 用例末尾必须往返闭合(见 case-round-trip skill)
│
└─ 否(任一不满足)
└→ function 级独立 context
- 每用例独立 browser.new_context() + new_page()
- 每用例独立登录
注意事项:
场景:同一 class 的多个用例形成线性流程链,后一个用例的起点是前一个用例的终点,不必从头登录。
test_a(搜索课程)
↓ 页面停留在搜索结果
test_b(点击课程 → 新 tab 打开课程首页)
↓ 新 tab 保存为 class 属性
test_c(在课程首页继续操作)
↓ 直接使用 class 属性中的 page
_login_setup 为 no-op,用 class_page + request.cls.page 共享type(self).<attr> = new_page),后续用例通过 self.<attr> 访问
class_pagefixture 的实现见 browser-config "Fixture 分层模板"。
class TestSomeFlow(BaseTest):
@pytest.fixture(autouse=True)
def _login_setup(self):
yield # no-op,覆盖父类
@pytest.fixture(scope="class", autouse=True)
def _shared_setup(self, class_page, token, request):
login_page = LoginPage(class_page)
login_page.login_with_token(BASE_URL, token)
request.cls.page = class_page
def test_step_1(self):
... # self.page 已由 _shared_setup 注入,class 级共享
def test_step_2(self):
new_page = some_page.click_open_new_tab()
type(self).detail_page = new_page # 保存到 class 属性供后续用例
def test_step_3(self):
detail = SomeDetailPage(self.detail_page) # 直接接力
...
Role<Role><Page>Page 命名、role_<page> 文件名前缀,继承 BasePagetests/<role>/<role>_base_test.py::<Role>BaseTest 继承 BaseTest,实现登录 + 切换 + 起点断言tests/<role>/test_<role>_flow.py::Test<Role>Flow 继承新基类pages/__init__.py 追加新页面导出本项目当前的落地情况(具体类名、fixture、起点页面)→ docs/architecture.md。