# Setup Playwright Automation

> Initialize and configure Playwright for fast, reliable web UI and mobile testing. Use when: modern browser automation needed, testing mobile web, implementing async/parallel testing, using Playwright's advanced features.

- Skill: `bavithiranhardy14/setup-playwright-automation` (Agent Skill)
- Install (CLI): `npx skillmds@latest add bavithiranhardy14/setup-playwright-automation`
- Raw SKILL.md: https://api.skillmd.com/api/skills/bavithiranhardy14/setup-playwright-automation/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: bavithiranhardy14 (https://skillmd.com/u/bavithiranhardy14)
- Updated: 2026-09-22
- Page: https://skillmd.com/skills/bavithiranhardy14/setup-playwright-automation

---


# Setup Playwright Automation

## When to Use

- Modern web application testing
- Mobile web testing (iOS, Android)
- Fast, reliable test execution
- Parallel/async testing requirements
- Advanced browser automation features
- Automatic wait strategies

## Procedure

### 1. Install Playwright

```bash
pip install playwright==1.36.0 pytest-playwright==0.3.0
# Download browsers
playwright install
```

### 2. Create Playwright Browser Factory

**factories/browser_factory.py**

```python
from playwright.sync_api import sync_playwright, expect
from config.settings import config
from utils.logger import get_logger

logger = get_logger(__name__)

class PlaywrightBrowserFactory:
    """Factory for Playwright browser instances."""
    
    BROWSERS = ["chromium", "firefox", "webkit"]
    
    @staticmethod
    def create_browser_context(browser_name="chromium", headless=True, **kwargs):
        playwright = sync_playwright().start()
        
        if browser_name == "chromium":
            browser = playwright.chromium.launch(headless=headless, **kwargs)
        elif browser_name == "firefox":
            browser = playwright.firefox.launch(headless=headless, **kwargs)
        elif browser_name == "webkit":
            browser = playwright.webkit.launch(headless=headless, **kwargs)
        else:
            raise ValueError(f"Unsupported browser: {browser_name}")
        
        context = browser.new_context(
            viewport={"width": 1280, "height": 720},
            ignore_https_errors=True
        )
        
        logger.info(f"Playwright {browser_name} context created (headless={headless})")
        return playwright, browser, context
    
    @staticmethod
    def create_mobile_browser(device_name="iPhone 12"):
        from playwright.sync_api import devices
        playwright = sync_playwright().start()
        browser = playwright.chromium.launch(headless=config.headless)
        context = browser.new_context(**devices[device_name])
        logger.info(f"Mobile browser created: {device_name}")
        return playwright, browser, context


class PlaywrightPage:
    """Wrapper for Playwright Page with common methods."""
    
    def __init__(self, page):
        self.page = page
    
    def goto(self, url):
        self.page.goto(url)
    
    def click(self, selector):
        self.page.click(selector)
    
    def fill(self, selector, text):
        self.page.fill(selector, text)
    
    def get_text(self, selector):
        return self.page.text_content(selector)
    
    def is_visible(self, selector):
        return self.page.is_visible(selector)
    
    def wait_for_load_state(self, state="networkidle"):
        self.page.wait_for_load_state(state)
    
    def screenshot(self, path):
        self.page.screenshot(path=path)
    
    def close(self):
        self.page.close()
```

### 3. Create Pytest Fixtures

**fixtures/playwright_fixtures.py**

```python
import pytest
from playwright.sync_api import sync_playwright
from factories.browser_factory import PlaywrightBrowserFactory, PlaywrightPage
from config.settings import config

@pytest.fixture(scope="session")
def playwright_instance():
    return sync_playwright().start()

@pytest.fixture(scope="function")
def browser_context():
    playwright, browser, context = PlaywrightBrowserFactory.create_browser_context(
        browser_name=config.browser_type,
        headless=config.headless
    )
    yield context
    context.close()
    browser.close()
    playwright.stop()

@pytest.fixture(scope="function")
def page(browser_context):
    page = browser_context.new_page()
    yield PlaywrightPage(page)
    page.close()

@pytest.fixture(scope="function")
def mobile_page():
    playwright, browser, context = PlaywrightBrowserFactory.create_mobile_browser("iPhone 12")
    page = context.new_page()
    yield PlaywrightPage(page)
    page.close()
    context.close()
    browser.close()
    playwright.stop()

@pytest.fixture(params=["chromium", "firefox", "webkit"])
def multi_browser_page(request):
    playwright, browser, context = PlaywrightBrowserFactory.create_browser_context(request.param)
    page = context.new_page()
    yield PlaywrightPage(page)
    page.close()
    context.close()
    browser.close()
    playwright.stop()
```

### 4. Create Base Page

**pages/playwright_base_page.py**

```python
from utils.logger import get_logger

logger = get_logger(__name__)

class PlaywrightBasePage:
    
    def __init__(self, page):
        self.page = page
        self.timeout = 10000
    
    def goto(self, url):
        self.page.goto(url)
    
    def click(self, selector):
        self.page.click(selector)
    
    def fill(self, selector, text):
        self.page.fill(selector, text)
    
    def get_text(self, selector):
        return self.page.text_content(selector)
    
    def is_visible(self, selector):
        return self.page.is_visible(selector)
    
    def wait_for_selector(self, selector):
        self.page.wait_for_selector(selector)
    
    def wait_for_load_state(self, state="networkidle"):
        self.page.wait_for_load_state(state)
    
    def screenshot(self, filename):
        self.page.screenshot(path=f"reports/screenshots/{filename}.png")
    
    def get_page_title(self):
        return self.page.title()
    
    def get_current_url(self):
        return self.page.url
```

### 5. Advanced Features

**Trace Recording**

```python
@pytest.fixture
def context_with_tracing(browser_context):
    browser_context.tracing.start(screenshots=True, snapshots=True, sources=True)
    yield browser_context
    browser_context.tracing.stop(path="trace.zip")
```

**Network Interception**

```python
def mock_api(page):
    page.route("**/api/**", lambda route: route.fulfill(
        status=200, json={"status": "ok"}
    ))
```

**Performance Metrics**

```python
def get_performance_metrics(page):
    return page.evaluate("() => JSON.stringify(window.performance)")
```

### 6. Run Commands

```bash
pytest tests/ui/ -m playwright
BROWSER=firefox pytest tests/ui/
HEADLESS=False pytest tests/ui/
pytest tests/ui/ -m mobile
pytest tests/ui/ --tracing on
pytest tests/ui/ -n 4
```

## Best Practices

- Use automatic wait strategies — no `time.sleep()`
- Leverage trace recording for debugging
- Use contexts for test isolation
- Intercept networks to mock APIs
- Run multi-browser via parametrized fixtures

