selenium-automation について
Web テストを作成する開発者向けの Selenium 自動化スキルです。WebDriver、ページオブジェクト設計、テストの信頼性向上を扱い、保守しやすいブラウザテストスイートの構築に役立ちます。
主な機能
- 01Selenium WebDriver によるブラウザ自動化
- 02Page Object Model の設計
- 03明示的な待機と動的コンテンツへの対応
- 04クロスブラウザおよびヘッドレステスト
- 05pytest などのテストフレームワーク連携
活用シーン
- 01保守しやすい Web アプリテストの構築
- 02動的なページ要素との同期
- 03複数ブラウザでのアプリ検証
- 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
要素の検索方法
推奨順(信頼性の高い順)
- ID - 使用可能な場合、最も信頼性が高い
- Name - フォーム要素に適している
- CSS Selector - 高速で読みやすい
- XPath - 強力だが、不安定になりやすい
- Link Text - アンカー要素に使用する
- 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()を使ってブレークポイントを設定する
コメント
Markdown 対応