selenium-automation
Selenium WebDriverを使用したブラウザ自動化とWebテストの専門的なサポートを提供します。要素の検索方法、待機処理、テストの構成管理におけるベストプラクティスを踏まえた実践的なガイダンスが得られます。
description の原文を見る
Expert guidance for browser automation and web testing using Selenium WebDriver with best practices for element location, waits, and test organization.
SKILL.md 本文
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 セットアップ
ドライバファクトリーパターン
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)
# 必要に応じて他のブラウザを追加
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)
Page Object の実装
from selenium.webdriver.common.by import By
from pages.base_page import BasePage
class LoginPage(BasePage):
# ロケーター
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 のベストプラクティス
# 良い例: 具体的で安定したセレクタ
By.CSS_SELECTOR, 'form#login input[name="username"]'
By.CSS_SELECTOR, '[data-testid="submit-button"]'
# 避けるべき: 脆弱なセレクタ
By.CSS_SELECTOR, 'div > div > div > button' # 構造依存が高い
By.CSS_SELECTOR, '.btn-primary' # クラスが変更される可能性
XPath のベストプラクティス
# 複雑な関係性に使用
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)
# 要素がクリック可能になるまで待機
element = wait.until(EC.element_to_be_clickable((By.ID, 'button')))
# 要素が表示されるまで待機
element = wait.until(EC.visibility_of_element_located((By.ID, 'modal')))
# テキストが表示されるまで待機
wait.until(EC.text_to_be_present_in_element((By.ID, 'status'), 'Complete'))
# カスタム待機条件
wait.until(lambda d: d.find_element(By.ID, 'count').text == '5')
一般的な Expected Conditions
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):
"""有効な認証情報でユーザーがログインできることを検証"""
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):
"""無効なパスワードのエラーメッセージが表示されることを検証"""
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() # OK をクリック
alert.dismiss() # キャンセルをクリック
alert.send_keys('input text') # プロンプトにテキストを入力
フレーム
driver.switch_to.frame('frame_name')
# または要素で指定
frame = driver.find_element(By.ID, 'myframe')
driver.switch_to.frame(frame)
# メインコンテンツに戻る
driver.switch_to.default_content()
複数のウィンドウ
original_window = driver.current_window_handle
# 新しいウィンドウを開くリンクをクリック
for handle in driver.window_handles:
if handle != original_window:
driver.switch_to.window(handle)
break
# 元のウィンドウに戻す
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()でブレークポイントを使用する
ライセンス: Apache-2.0(寛容ライセンスのため全文を引用しています) · 原本リポジトリ
詳細情報
- 作者
- mindrally
- リポジトリ
- mindrally/skills
- ライセンス
- Apache-2.0
- 最終更新
- 不明
Source: https://github.com/mindrally/skills / ライセンス: Apache-2.0
関連スキル
doubt-driven-development
重要な判断はすべて、本番環境への展開前に新しい視点から対抗的レビューを実施します。速度より正確性が重要な場合、不慣れなコードを扱う場合、本番環境・セキュリティに関わるロジック・取り消し不可の操作など影響度が高い場合、または後でバグを修正するよりも今検証する方が効率的な場合に活用してください。
apprun-skills
TypeScriptを使用したAppRunアプリケーションのMVU設計に関する総合的なガイダンスが得られます。コンポーネントパターン、イベントハンドリング、状態管理(非同期ジェネレータを含む)、パラメータと保護機能を備えたルーティング・ナビゲーション、vistestを使用したテストに対応しています。AppRunコンポーネントの設計・レビュー、ルートの配線、状態フローの管理、AppRunテストの作成時に活用してください。
desloppify
コードベースのヘルスチェックと技術負債の追跡ツールです。コード品質、技術負債、デッドコード、大規模ファイル、ゴッドクラス、重複関数、コードスメル、命名規則の問題、インポートサイクル、結合度の問題についてユーザーが質問した場合に使用してください。また、ヘルススコアの確認、次の改善項目の提案、クリーンアップ計画の作成をリクエストされた際にも対応します。29言語に対応しています。
debugging-and-error-recovery
テストが失敗したり、ビルドが壊れたり、動作が期待と異なったり、予期しないエラーが発生したりした場合に、体系的な根本原因デバッグをガイドします。推測ではなく、根本原因を見つけて修正するための体系的なアプローチが必要な場合に使用してください。
test-driven-development
テスト駆動開発により実装を進めます。ロジックの実装、バグの修正、動作の変更など、あらゆる場面で活用できます。コードが正常に動作することを証明する必要がある場合、バグ報告を受けた場合、既存機能を修正する予定がある場合に使用してください。
incremental-implementation
変更を段階的に実施します。複数のファイルに影響する機能や変更を実装する場合に使用してください。大量のコードを一度に書こうとしている場合や、タスクが一度では完結できないほど大きい場合に活用します。