Skip to main content
skill CX Codex

selenium-automation — Claude Code skill: Selenium WebDriver tests

A skill that steers your coding agent toward solid Selenium WebDriver tests: Page Object Model, explicit waits, stable locators.

Install into Claude Code · Skills CLI (Vercel) All methods and platforms ↓
npx skills add Mindrally/skills --skill selenium-automation -a claude-code
Open on GitHub

What selenium-automation does

This skill turns the assistant into a Selenium WebDriver tutor. It covers element location, waiting for dynamic content, and splitting tests across files so a markup change does not break the whole suite.

The material is architectural: a driver factory, a base page class with find_element, click_element and enter_text, pytest fixtures, and a folder layout with pages/, tests/ and utils/. Locator strategies are ranked from ID down to XPath, and the common expected conditions such as element_to_be_clickable and visibility_of_element_located get their own section.

The core rule is explicit waits over implicitly_wait and hard-coded sleeps. Worth knowing: the sample fixture still sets an implicit wait of 10 seconds, so you will be editing the reference code to match the advice. The examples assume Python, Selenium and webdriver_manager.

What it helps with

  • split tests into page objects instead of copy-paste
  • swap sleeps for explicit element waits
  • pick a stable locator over a long div chain
  • set up a driver factory for Chrome and headless runs
  • wire pages into tests through pytest fixtures

Example prompts for the agent

  • write a Selenium page object for the login screen
  • rewrite this test to use explicit waits instead of sleep
  • suggest locators for the sign-in form using data-testid

How to install selenium-automation

1Skills CLI (Vercel)

npx skills add Mindrally/skills --skill selenium-automation -a claude-code

2Manually: put the files in place

~/.claude/skills/selenium-automation/SKILL.md

Copy the whole skill folder; for one project use .claude/skills/selenium-automation/

Step by step, with commands for each platform: How to install skills in Claude Code: five ways

Questions about selenium-automation

How do I install selenium-automation in Claude?

Run npx skills add Mindrally/skills --skill selenium-automation -a claude-code. The skill file then lands at ~/.claude/skills/selenium-automation/SKILL.md.

What does selenium-automation do?

It gives the agent guidance on browser automation with Selenium WebDriver: locator choice, waits, the Page Object Model and test organization.

What do the skill's examples require?

They are written in Python with Selenium and webdriver_manager, and the tests use pytest. The browser driver is fetched through ChromeDriverManager.

Source text

SKILL.md · Apache-2.0
---
name: selenium-automation
description: Expert guidance for browser automation and web testing using Selenium WebDriver with best practices for element location, waits, and test organization.
metadata:
  maintainer: Mindrally
  source: https://github.com/Mindrally/skills
---

# Selenium Browser Automation

You are an expert in Selenium WebDriver, browser automation, web testing, and building reliable automated test suites for web applications.

## Core Expertise
- Selenium WebDriver architecture and browser drivers
- Element location strategies (ID, CSS, XPath, link text)
- Explicit and implicit waits for dynamic content
- Page Object Model (POM) design pattern
- Cross-browser testing with Chrome, Firefox, Safari, Edge
- Headless browser execution
- Integration with pytest, unittest, and other test frameworks
- Grid deployment for parallel test execution

## Key Principles

- Write maintainable, readable test code following PEP 8 style guidelines
- Implement the Page Object Model pattern for code reusability
- Use explicit waits instead of implicit waits or hard-coded sleeps
- Design tests for independence and isolation
- Handle dynamic content and asynchronous operations properly
- Follow DRY principles with helper functions and base classes

## Project Structure

```
tests/
    conftest.py
    pages/
        __init__.py
        base_page.py
        login_page.py
        dashboard_page.py
    tests/
        __init__.py
        test_login.py
        test_dashboard.py
    utils/
        __init__.py
        driver_factory.py
        config.py
```

## WebDriver Setup

### Driver Factory Pattern
```python
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.chrome.service import Service

def create_driver(browser='chrome', headless=False):
    if browser == 'chrome':
        options = Options()
        if headless:
            options.add_argument('--headless')
        options.add_argument('--no-sandbox')
        options.add_argument('--disable-dev-shm-usage')
        service = Service(ChromeDriverManager().install())
        return webdriver.Chrome(service=service, options=options)
    # Add other browsers as needed
```

### Pytest Fixtures
```python
import pytest
from utils.driver_factory import create_driver

@pytest.fixture(scope='function')
def driver():
    driver = create_driver(headless=True)
    driver.implicitly_wait(10)
    yield driver
    driver.quit()
```

## Page Object Model

### Base Page Class
```python
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

class BasePage:
    def __init__(self, driver):
        self.driver = driver
        self.wait = WebDriverWait(driver, 10)

    def find_element(self, locator):
        return self.wait.until(EC.presence_of_element_located(locator))

    def click_element(self, locator):
        element = self.wait.until(EC.element_to_be_clickable(locator))
        element.click()

    def enter_text(self, locator, text):
        element = self.find_element(locator)
        element.clear()
        element.send_keys(text)
```

### Page Object Implementation
```python
from selenium.webdriver.common.by import By
from pages.base_page import BasePage

class LoginPage(BasePage):
    # Locators
    USERNAME_INPUT = (By.ID, 'username')
    PASSWORD_INPUT = (By.ID, 'password')
    LOGIN_BUTTON = (By.CSS_SELECTOR, 'button[type="submit"]')
    ERROR_MESSAGE = (By.CLASS_NAME, 'error-message')

    def __init__(self, driver):
        super().__init__(driver)
        self.url = '/login'

    def login(self, username, password):
        self.enter_text(self.USERNAME_INPUT, username)
        self.enter_text(self.PASSWORD_INPUT, password)
        self.click_element(self.LOGIN_BUTTON)

    def get_error_message(self):
        return self.find_element(self.ERROR_MESSAGE).text
```

## Element Location Strategies

### Preferred Order (Most to Least Reliable)
1. **ID** - Most reliable when available
2. **Name** - Good for form elements
3. **CSS Selector** - Fast and readable
4. **XPath** - Powerful but can be brittle
5. **Link Text** - For anchor elements
6. **Class Name** - Avoid if class changes frequently

### CSS Selector Best Practices
```python
# Good: Specific, stable selectors
By.CSS_SELECTOR, 'form#login input[name="username"]'
By.CSS_SELECTOR, '[data-testid="submit-button"]'

# Avoid: Fragile selectors
By.CSS_SELECTOR, 'div > div > div > button'  # Too structural
By.CSS_SELECTOR, '.btn-primary'  # Class might change
```

### XPath Best Practices
```python
# Use for complex relationships
By.XPATH, '//label[text()="Email"]/following-sibling::input'
By.XPATH, '//table//tr[contains(., "John")]//button[@class="edit"]'
```

## Waits and Synchronization

### Explicit Waits (Preferred)
```python
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

wait = WebDriverWait(driver, 10)

# Wait for element to be clickable
element = wait.until(EC.element_to_be_clickable((By.ID, 'button')))

# Wait for element to be visible
element = wait.until(EC.visibility_of_element_located((By.ID, 'modal')))

# Wait for text to be present
wait.until(EC.text_to_be_present_in_element((By.ID, 'status'), 'Complete'))

# Custom wait condition
wait.until(lambda d: d.find_element(By.ID, 'count').text == '5')
```

### Common Expected Conditions
- `presence_of_element_located` - Element exists in DOM
- `visibility_of_element_located` - Element is visible
- `element_to_be_clickable` - Element is visible and enabled
- `staleness_of` - Element is no longer attached to DOM
- `frame_to_be_available_and_switch_to_it` - Frame is available

## Test Writing Best Practices

### Test Structure
```python
import pytest
from pages.login_page import LoginPage
from pages.dashboard_page import DashboardPage

class TestLogin:
    @pytest.fixture(autouse=True)
    def setup(self, driver):
        self.driver = driver
        self.login_page = LoginPage(driver)
        self.dashboard_page = DashboardPage(driver)

    def test_successful_login(self):
        """Verify user can login with valid credentials"""
        self.driver.get('https://example.com/login')
        self.login_page.login('valid_user', 'valid_pass')
        assert self.dashboard_page.is_displayed()

    def test_invalid_password_shows_error(self):
        """Verify error message displays for invalid password"""
        self.driver.get('https://example.com/login')
        self.login_page.login('valid_user', 'wrong_pass')
        assert 'Invalid credentials' in self.login_page.get_error_message()
```

### Test Naming Conventions
- Use descriptive names: `test_login_with_valid_credentials_redirects_to_dashboard`
- Include the action and expected outcome
- Group related tests in classes

## Handling Special Elements

### Dropdowns
```python
from selenium.webdriver.support.ui import Select

select = Select(driver.find_element(By.ID, 'country'))
select.select_by_visible_text('United States')
select.select_by_value('us')
select.select_by_index(1)
```

### Alerts
```python
alert = driver.switch_to.alert
alert.accept()  # Click OK
alert.dismiss()  # Click Cancel
alert.send_keys('input text')  # Type in prompt
```

### Frames
```python
driver.switch_to.frame('frame_name')
# Or by element
frame = driver.find_element(By.ID, 'myframe')
driver.switch_to.frame(frame)
# Return to main content
driver.switch_to.default_content()
```

### Multiple Windows
```python
original_window = driver.current_window_handle
# Click link that opens new window
for handle in driver.window_handles:
    if handle != original_window:
        driver.switch_to.window(handle)
        break
# Return to original
driver.switch_to.window(original_window)
```

## Performance and Reliability

- Run tests in headless mode for faster execution
- Use parallel execution with pytest-xdist
- Implement retry logic for flaky tests
- Take screenshots on failure for debugging
- Use WebDriverWait instead of time.sleep()

## Key Dependencies

- selenium
- webdriver-manager
- pytest
- pytest-xdist (parallel execution)
- pytest-html (HTML reports)
- allure-pytest (advanced reporting)

## Configuration

```python
# pytest.ini
[pytest]
addopts = -v --html=reports/report.html
markers =
    smoke: Quick smoke tests
    regression: Full regression tests
```

## Debugging Tips

- Enable browser developer tools in non-headless mode
- Use `driver.save_screenshot('debug.png')` for visual debugging
- Print page source: `print(driver.page_source)`
- Use breakpoints with `import pdb; pdb.set_trace()`

© Mindrally · Apache-2.0 · Mindrally/skills

Similar skills

Everything for Testing and QA →

From the same set168

technical-writing Enforces strict technical writing rules for developer tutorials and documentation. It eliminates cliches and bullet lists to produce deep, practical implementation guides. CX Codex +1 1,200installs css This skill hands the agent a set of CSS rules: Flexbox, Grid, custom properties, BEM and specificity control. Useful when AI writes your styles. CX Codex +1 1,200installs modern-web-development A rule set for the modern web stack: TypeScript, Next.js 14, React Server Components, Supabase, GraphQL and Tailwind CSS. Useful when your agent writes frontend and API code in the same repo. CX Codex +1 1,200installs ci-cd-best-practices Provides guidelines for automated pipelines, testing workflows, and zero-downtime deployment patterns. Works with assistants supporting pipeline generation and DevOps tasks. CX Codex +1 1,200installs systemverilog A skill that gives your agent SystemVerilog rules for FPGA and ASIC work: modular structure, synchronous design, timing closure and verification. CX Codex +1 1,100installs fpga SystemVerilog and Vivado hardware design guidelines covering timing closure, AXI interfaces, resource savings, and testbench verification. CX Codex +1 1,100installs php-development This skill makes your coding agent write PHP 8+ the disciplined way: SOLID, PSR-12, strict types, PHPUnit tests. Useful once a PHP codebase outgrows one person's habits. CX Codex +1 1,100installs gitlab-workflow Adds GitLab practices to coding assistants, covering merge request guidelines and multi-stage .gitlab-ci.yml pipelines. CX Codex +1 1,100installs

Project sponsors

Companies that keep this analytics open
Gold sponsor

Impressions, clicks and code copies — open statistics. We keep the numbers public for the same reason NeBlask itself is public. Become a sponsor