mcpField
S
selenium-automation

selenium-automation

github.com/mindrallyテスト・品質2871.2k 回インストール3 週間前に更新
リポジトリ

selenium-automation について

Web テストを作成する開発者向けの Selenium 自動化スキルです。WebDriver、ページオブジェクト設計、テストの信頼性向上を扱い、保守しやすいブラウザテストスイートの構築に役立ちます。

主な機能

  1. 01Selenium WebDriver によるブラウザ自動化
  2. 02Page Object Model の設計
  3. 03明示的な待機と動的コンテンツへの対応
  4. 04クロスブラウザおよびヘッドレステスト
  5. 05pytest などのテストフレームワーク連携

活用シーン

  1. 01保守しやすい Web アプリテストの構築
  2. 02動的なページ要素との同期
  3. 03複数ブラウザでのアプリ検証
  4. 04pytest によるテストの並列実行

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/mindrally/skills --skill selenium-automation

インストール後、Claude Code で/selenium-automationを入力して読み込まれたか確認します。

詳細

Selenium ブラウザー自動化

Selenium WebDriver、ブラウザー自動化、Web テスト、および Web アプリケーション向けの信頼性の高い自動テストスイートの構築に精通しています。

主な専門分野

  • Selenium WebDriver のアーキテクチャとブラウザードライバー
  • 要素の検索方法(ID、CSS、XPath、リンクテキスト)
  • 動的コンテンツに対する明示的および暗黙的な待機
  • Page Object Model(POM)の設計パターン
  • Chrome、Firefox、Safari、Edge を使ったクロスブラウザーテスト
  • ヘッドレスブラウザーの実行
  • pytest、unittest、その他のテストフレームワークとの統合
  • 並列テスト実行のための Grid のデプロイ

主な原則

  • PEP 8 のスタイルガイドラインに従い、保守しやすく読みやすいテストコードを記述する
  • コードを再利用できるよう、Page Object Model パターンを実装する
  • 暗黙的な待機やハードコードされたスリープではなく、明示的な待機を使用する
  • テストの独立性と分離性を確保する
  • 動的コンテンツや非同期処理を適切に扱う
  • ヘルパー関数と基底クラスを使い、DRY 原則に従う

プロジェクト構成

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 のセットアップ

Driver Factory パターン
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 フィクスチャ
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

基底ページクラス
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)
ページオブジェクトの実装
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

要素の検索方法

推奨順(信頼性の高い順)
  1. ID - 使用可能な場合、最も信頼性が高い
  2. Name - フォーム要素に適している
  3. CSS Selector - 高速で読みやすい
  4. XPath - 強力だが、不安定になりやすい
  5. Link Text - アンカー要素に使用する
  6. Class Name - クラスが頻繁に変更される場合は避ける
CSS Selector のベストプラクティス
# 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 のベストプラクティス
# Use for complex relationships
By.XPATH, '//label[text()="Email"]/following-sibling::input'
By.XPATH, '//table//tr[contains(., "John")]//button[@class="edit"]'

待機と同期

明示的な待機(推奨)
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')
よく使われる期待条件
  • presence_of_element_located - 要素が DOM に存在する
  • visibility_of_element_located - 要素が表示されている
  • element_to_be_clickable - 要素が表示され、操作可能である
  • staleness_of - 要素が DOM にアタッチされていない
  • frame_to_be_available_and_switch_to_it - フレームが利用可能である

テスト作成のベストプラクティス

テストの構成
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_login_with_valid_credentials_redirects_to_dashboard
  • 操作と期待する結果を含める
  • 関連するテストをクラスにまとめる

特殊な要素の扱い

ドロップダウン
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)
アラート
alert = driver.switch_to.alert
alert.accept()  # Click OK
alert.dismiss()  # Click Cancel
alert.send_keys('input text')  # Type in prompt
フレーム
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()
複数のウィンドウ
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)

パフォーマンスと信頼性

  • 実行を高速化するため、ヘッドレスモードでテストを実行する
  • pytest-xdist を使って並列実行する
  • 不安定なテストには再試行ロジックを実装する
  • デバッグ用に失敗時のスクリーンショットを撮影する
  • time.sleep() ではなく WebDriverWait を使用する

主な依存関係

  • selenium
  • webdriver-manager
  • pytest
  • pytest-xdist(並列実行)
  • pytest-html(HTML レポート)
  • allure-pytest(高度なレポート機能)

設定

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

デバッグのヒント

  • ヘッドレスモードではない場合、ブラウザーの開発者ツールを有効にする
  • 視覚的なデバッグには driver.save_screenshot('debug.png') を使用する
  • ページソースを出力する:print(driver.page_source)
  • import pdb; pdb.set_trace() を使ってブレークポイントを設定する

コメント