QA Playwright Python Writer
Purpose
Write Playwright E2E tests for Python from test case specifications. Transform structured test cases into executable Playwright Python test files with pytest-playwright, Page Object Model, auto-waiting, multi-browser support, and optional live browser record mode.
Trigger Phrases
- "Write Playwright Python tests for [feature/flow]"
- "Generate Playwright E2E tests in Python"
- "Create pytest-playwright tests"
- "Add Playwright tests with record mode (Python)"
- "Playwright Python tests for [URL/flow]"
- "POM-based Playwright tests in Python"
- "pytest-playwright tests for [page]"
- "Heal my failing Playwright Python tests"
Three Modes
| Mode |
When to Use |
Behavior |
| Record Mode |
User wants live browser capture |
Use Playwright MCP (e.g., cursor-ide-browser) → navigate, interact, capture interactions → generate Python test code from recorded steps |
| Generate Mode |
Default; from test case specs |
Read test cases (from qa-testcase-from-docs, qa-testcase-from-ui, qa-manual-test-designer) → generate Playwright Python code |
| Heal Mode |
Tests fail after changes |
Delegate to qa-test-healer to auto-fix broken selectors, assertions, waits; mark unfixable as pytest.mark.skip |
Key Features
| Feature |
Description |
| Sync/Async API |
Default sync API; async via playwright_pytest_asyncio = True in pytest config |
| pytest-playwright |
Fixtures: page, browser, context, playwright; integrates with pytest |
| POM pattern |
Base page classes, page-specific classes, component objects |
| Auto-wait |
Playwright auto-waits for elements; avoid page.wait_for_timeout |
| Multi-browser |
Chromium, Firefox, WebKit via pytest-playwright browser options |
| Network interception |
page.route for API mocking, request/response handling |
Workflow
- Read test cases — From specs, requirements, or manual test designs
- Analyze app — Inspect pages, flows, selectors (or use Record Mode)
- Generate tests — Produce
test_{feature}.py with POM where appropriate
- Configure — Add/update
conftest.py, pytest.ini or pyproject.toml
- Run — User runs
pytest to execute tests
E2E Testing
- Navigation:
page.goto(), page.go_back(), page.reload()
- Interactions:
click(), fill(), select_option(), check(), hover(), press()
- Assertions:
expect(locator).to_be_visible(), to_have_text(), to_have_url(), etc.
- Network:
page.route() for API mocking, request/response interception
- Auto-wait: Playwright auto-waits; avoid
page.wait_for_timeout()
See references/patterns.md for navigation, forms, auth, file upload, drag-drop, iframes, multi-tab, API mocking, visual comparison.
Page Object Model (POM)
- Base page: Shared selectors, navigation helpers, common actions
- Page-specific: Extend base; encapsulate page-specific locators and methods
- Component objects: Reusable components (header, modal, form) as classes
See references/best-practices.md for POM structure.
Key Patterns
- Structure:
def test_*() functions; pytest.mark for grouping; conftest.py for fixtures
- Locators:
get_by_role > get_by_test_id > get_by_text > get_by_label > CSS selector
- Assertions:
expect(locator).to_be_visible(), to_have_text(), to_have_url(), to_have_count(), etc.
- Network:
page.route(url, handler) for mocking; page.unroute() to clear
- Fixtures:
page, browser, context, playwright from pytest-playwright; custom fixtures in conftest.py
See references/patterns.md for full pattern reference.
Locator Priority
- get_by_role — Accessibility-based; most resilient
- get_by_test_id —
data-testid; explicit, stable
- get_by_text — Visible text; use for unique labels
- get_by_label — Form labels; good for inputs
- CSS selector — Last resort; brittle for dynamic content
File Naming
- Tests:
test_{feature}.py (e.g., test_login.py, test_checkout.py)
- Fixtures:
conftest.py in test directory or package root
- Page objects:
pages/ or page_objects/ directory
Configuration
- pytest.ini / pyproject.toml — pytest options, markers, playwright settings
- conftest.py — Shared fixtures, base URL, browser options
- pytest-playwright — Provides
page, browser, context fixtures
See references/config.md for full config guide.
MCP Integration
- Context7 MCP — Fetch Playwright Python documentation when needed
- Playwright MCP (cursor-ide-browser, @playwright/mcp) — Record mode: navigate, snapshot, click, type; capture interactions → generate Python test code
Scope
Can do (autonomous):
- Generate Playwright E2E tests in Python from test case specs
- Use Record Mode with Playwright MCP to capture and generate tests
- Apply POM pattern, stable locators, auto-wait
- Configure conftest.py, pytest.ini, pyproject.toml for pytest-playwright
- Use
page.route() for API mocking
- Delegate to qa-test-healer when tests fail (Heal Mode)
- Use Context7 MCP for Playwright Python docs
Cannot do (requires confirmation):
- Change production code structure
- Add dependencies not in requirements.txt / pyproject.toml
- Override project pytest/playwright config without approval
- Navigate to URLs not provided (Record Mode)
Will not do (out of scope):
- Execute tests (user runs
pytest)
- Write pytest unit tests without Playwright (use qa-pytest-writer)
- Modify CI/CD pipelines
- Bypass security or access restricted areas
References
references/patterns.md — Sync vs async, pytest fixtures, POM, network mocking
references/config.md — pytest-playwright, conftest.py, pytest.ini, browser config
references/best-practices.md — POM, locators, async patterns, test isolation
Quality Checklist
Troubleshooting
| Symptom |
Likely Cause |
Fix |
| Element not found |
Selector too specific, dynamic content |
Use get_by_role/get_by_test_id; add data-testid if needed |
| Timeout |
Element not ready, slow network |
Increase expect timeout; use wait_for; check for overlays |
| Flaky tests |
Race conditions, shared state |
Ensure test isolation; use auto-wait; avoid fixed delays |
| Record mode empty |
MCP not capturing steps |
Verify Playwright MCP active; lock browser before actions |
| Sync/async conflict |
Mixing sync and async fixtures |
Use one mode per file; set playwright_pytest_asyncio consistently |
| API mock not applied |
Route registered after request |
Call page.route before page.goto |
| Fixture not found |
conftest.py not in path |
Ensure conftest.py in test directory or parent |
1---2name: qa-playwright-py-writer3description: Generate Playwright E2E tests for Python with async/sync API, pytest-playwright integration, POM pattern, and live browser record mode via Playwright MCP.4---56# QA Playwright Python Writer78## Purpose910Write Playwright E2E tests for Python from test case specifications. Transform structured test cases into executable Playwright Python test files with pytest-playwright, Page Object Model, auto-waiting, multi-browser support, and optional live browser record mode.1112## Trigger Phrases1314- "Write Playwright Python tests for [feature/flow]"15- "Generate Playwright E2E tests in Python"16- "Create pytest-playwright tests"17- "Add Playwright tests with record mode (Python)"18- "Playwright Python tests for [URL/flow]"19- "POM-based Playwright tests in Python"20- "pytest-playwright tests for [page]"21- "Heal my failing Playwright Python tests"2223## Three Modes2425| Mode | When to Use | Behavior |26|------|-------------|----------|27| **Record Mode** | User wants live browser capture | Use Playwright MCP (e.g., cursor-ide-browser) → navigate, interact, capture interactions → generate Python test code from recorded steps |28| **Generate Mode** | Default; from test case specs | Read test cases (from qa-testcase-from-docs, qa-testcase-from-ui, qa-manual-test-designer) → generate Playwright Python code |29| **Heal Mode** | Tests fail after changes | Delegate to **qa-test-healer** to auto-fix broken selectors, assertions, waits; mark unfixable as `pytest.mark.skip` |3031## Key Features3233| Feature | Description |34|---------|-------------|35| **Sync/Async API** | Default sync API; async via `playwright_pytest_asyncio = True` in pytest config |36| **pytest-playwright** | Fixtures: `page`, `browser`, `context`, `playwright`; integrates with pytest |37| **POM pattern** | Base page classes, page-specific classes, component objects |38| **Auto-wait** | Playwright auto-waits for elements; avoid `page.wait_for_timeout` |39| **Multi-browser** | Chromium, Firefox, WebKit via pytest-playwright browser options |40| **Network interception** | `page.route` for API mocking, request/response handling |4142## Workflow43441. **Read test cases** — From specs, requirements, or manual test designs452. **Analyze app** — Inspect pages, flows, selectors (or use Record Mode)463. **Generate tests** — Produce `test_{feature}.py` with POM where appropriate474. **Configure** — Add/update `conftest.py`, `pytest.ini` or `pyproject.toml`485. **Run** — User runs `pytest` to execute tests4950## E2E Testing5152- **Navigation:** `page.goto()`, `page.go_back()`, `page.reload()`53- **Interactions:** `click()`, `fill()`, `select_option()`, `check()`, `hover()`, `press()`54- **Assertions:** `expect(locator).to_be_visible()`, `to_have_text()`, `to_have_url()`, etc.55- **Network:** `page.route()` for API mocking, request/response interception56- **Auto-wait:** Playwright auto-waits; avoid `page.wait_for_timeout()`5758See `references/patterns.md` for navigation, forms, auth, file upload, drag-drop, iframes, multi-tab, API mocking, visual comparison.5960## Page Object Model (POM)6162- **Base page:** Shared selectors, navigation helpers, common actions63- **Page-specific:** Extend base; encapsulate page-specific locators and methods64- **Component objects:** Reusable components (header, modal, form) as classes6566See `references/best-practices.md` for POM structure.6768## Key Patterns6970- **Structure:** `def test_*()` functions; `pytest.mark` for grouping; `conftest.py` for fixtures71- **Locators:** `get_by_role` > `get_by_test_id` > `get_by_text` > `get_by_label` > CSS selector72- **Assertions:** `expect(locator).to_be_visible()`, `to_have_text()`, `to_have_url()`, `to_have_count()`, etc.73- **Network:** `page.route(url, handler)` for mocking; `page.unroute()` to clear74- **Fixtures:** `page`, `browser`, `context`, `playwright` from pytest-playwright; custom fixtures in conftest.py7576See `references/patterns.md` for full pattern reference.7778## Locator Priority79801. **get_by_role** — Accessibility-based; most resilient812. **get_by_test_id** — `data-testid`; explicit, stable823. **get_by_text** — Visible text; use for unique labels834. **get_by_label** — Form labels; good for inputs845. **CSS selector** — Last resort; brittle for dynamic content8586## File Naming8788- **Tests:** `test_{feature}.py` (e.g., `test_login.py`, `test_checkout.py`)89- **Fixtures:** `conftest.py` in test directory or package root90- **Page objects:** `pages/` or `page_objects/` directory9192## Configuration9394- **pytest.ini** / **pyproject.toml** — pytest options, markers, playwright settings95- **conftest.py** — Shared fixtures, base URL, browser options96- **pytest-playwright** — Provides `page`, `browser`, `context` fixtures9798See `references/config.md` for full config guide.99100## MCP Integration101102- **Context7 MCP** — Fetch Playwright Python documentation when needed103- **Playwright MCP** (cursor-ide-browser, @playwright/mcp) — Record mode: navigate, snapshot, click, type; capture interactions → generate Python test code104105## Scope106107**Can do (autonomous):**108- Generate Playwright E2E tests in Python from test case specs109- Use Record Mode with Playwright MCP to capture and generate tests110- Apply POM pattern, stable locators, auto-wait111- Configure conftest.py, pytest.ini, pyproject.toml for pytest-playwright112- Use `page.route()` for API mocking113- Delegate to qa-test-healer when tests fail (Heal Mode)114- Use Context7 MCP for Playwright Python docs115116**Cannot do (requires confirmation):**117- Change production code structure118- Add dependencies not in requirements.txt / pyproject.toml119- Override project pytest/playwright config without approval120- Navigate to URLs not provided (Record Mode)121122**Will not do (out of scope):**123- Execute tests (user runs `pytest`)124- Write pytest unit tests without Playwright (use qa-pytest-writer)125- Modify CI/CD pipelines126- Bypass security or access restricted areas127128## References129130- `references/patterns.md` — Sync vs async, pytest fixtures, POM, network mocking131- `references/config.md` — pytest-playwright, conftest.py, pytest.ini, browser config132- `references/best-practices.md` — POM, locators, async patterns, test isolation133134## Quality Checklist135136- [ ] Auto-wait used; no `page.wait_for_timeout` (use `expect` with timeout or `wait_for`)137- [ ] No hardcoded waits; prefer `expect` auto-retry138- [ ] POM pattern applied for page-specific logic139- [ ] Stable locators (get_by_role, get_by_test_id preferred)140- [ ] Tests independent (no shared state, order-independent)141- [ ] Proper teardown (fixtures, conftest if needed)142- [ ] Traceability to test case IDs where applicable143- [ ] No hardcoded secrets (use env vars)144145## Troubleshooting146147| Symptom | Likely Cause | Fix |148|---------|--------------|-----|149| Element not found | Selector too specific, dynamic content | Use get_by_role/get_by_test_id; add data-testid if needed |150| Timeout | Element not ready, slow network | Increase expect timeout; use wait_for; check for overlays |151| Flaky tests | Race conditions, shared state | Ensure test isolation; use auto-wait; avoid fixed delays |152| Record mode empty | MCP not capturing steps | Verify Playwright MCP active; lock browser before actions |153| Sync/async conflict | Mixing sync and async fixtures | Use one mode per file; set playwright_pytest_asyncio consistently |154| API mock not applied | Route registered after request | Call page.route before page.goto |155| Fixture not found | conftest.py not in path | Ensure conftest.py in test directory or parent |